refactor(webworkers): move webworkers to separate @angular/platform-webworker and @angular/platform-webworker-dynamic packages

BREAKING CHANGE: web worker platform is now exported via separate packages.

Please use @angular/platform-webworker and @angular/platform-webworker-dynamic
This commit is contained in:
Igor Minar
2016-08-30 11:15:25 -07:00
committed by Victor Berchet
parent 0f68351979
commit 71ae2c4525
84 changed files with 561 additions and 305 deletions

View File

@ -20,8 +20,6 @@ import {supportsState} from './history';
* `PlatformLocation` encapsulates all of the direct calls to platform APIs.
* This class should not be used directly by an application developer. Instead, use
* {@link Location}.
*
* @stable
*/
@Injectable()
export class BrowserPlatformLocation extends PlatformLocation {
@ -40,7 +38,6 @@ export class BrowserPlatformLocation extends PlatformLocation {
this._history = getDOM().getHistory();
}
/** @internal */
get location(): Location { return this._location; }
getBaseHrefFromDOM(): string { return getDOM().getBaseHref(); }

View File

@ -7,25 +7,14 @@
*/
export {BrowserModule, platformBrowser} from './browser';
export {BrowserPlatformLocation} from './browser/location/browser_platform_location';
export {Title} from './browser/title';
export {disableDebugTools, enableDebugTools} from './browser/tools/tools';
export {AnimationDriver} from './dom/animation_driver';
export {By} from './dom/debug/by';
export {NgProbeToken} from './dom/debug/ng_probe';
export {DOCUMENT} from './dom/dom_tokens';
export {EVENT_MANAGER_PLUGINS, EventManager} from './dom/events/event_manager';
export {HAMMER_GESTURE_CONFIG, HammerGestureConfig} from './dom/events/hammer_gestures';
export {DomSanitizer, SafeHtml, SafeResourceUrl, SafeScript, SafeStyle, SafeUrl} from './security/dom_sanitization_service';
// Web Workers
export {ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments} from './web_workers/shared/client_message_broker';
export {PRIMITIVE} from './web_workers/shared/serializer';
export {ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory} from './web_workers/shared/service_message_broker';
export * from './web_workers/shared/message_bus';
export {WORKER_APP_LOCATION_PROVIDERS} from './web_workers/worker/location_providers';
export {WORKER_UI_LOCATION_PROVIDERS} from './web_workers/ui/location_providers';
export {NgProbeToken} from './dom/debug/ng_probe';
export {platformWorkerUi, WebWorkerInstance, WORKER_SCRIPT, WORKER_UI_STARTABLE_MESSAGING_SERVICE} from './worker_render';
export {platformWorkerApp, WorkerAppModule} from './worker_app';
export * from './private_export';

View File

@ -9,40 +9,62 @@ import {ClassProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider
import * as browser from './browser';
import * as browserDomAdapter from './browser/browser_adapter';
import * as location from './browser/location/browser_platform_location';
import * as testability from './browser/testability';
import * as ng_probe from './dom/debug/ng_probe';
import * as dom_adapter from './dom/dom_adapter';
import * as dom_renderer from './dom/dom_renderer';
import * as dom_events from './dom/events/dom_events';
import * as hammer_gesture from './dom/events/hammer_gestures';
import * as key_events from './dom/events/key_events';
import * as shared_styles_host from './dom/shared_styles_host';
export var __platform_browser_private__: {
_DomAdapter?: typeof dom_adapter.DomAdapter; DomAdapter: typeof dom_adapter.DomAdapter;
_BrowserDomAdapter?: typeof browserDomAdapter.BrowserDomAdapter;
BrowserDomAdapter: typeof browserDomAdapter.BrowserDomAdapter;
getDOM: typeof dom_adapter.getDOM;
setRootDomAdapter: typeof dom_adapter.setRootDomAdapter;
_DomRootRenderer_?: typeof dom_renderer.DomRootRenderer;
DomRootRenderer_: typeof dom_renderer.DomRootRenderer_;
_DomSharedStylesHost?: typeof shared_styles_host.DomSharedStylesHost;
DomSharedStylesHost: typeof shared_styles_host.DomSharedStylesHost;
_SharedStylesHost?: typeof shared_styles_host.SharedStylesHost;
SharedStylesHost: typeof shared_styles_host.SharedStylesHost;
ELEMENT_PROBE_PROVIDERS: typeof ng_probe.ELEMENT_PROBE_PROVIDERS;
_DomEventsPlugin?: typeof dom_events.DomEventsPlugin;
DomEventsPlugin: typeof dom_events.DomEventsPlugin;
_initDomAdapter?: typeof browser.initDomAdapter,
_BrowserPlatformLocation?: location.BrowserPlatformLocation,
BrowserPlatformLocation: typeof location.BrowserPlatformLocation,
_DomAdapter?: dom_adapter.DomAdapter,
DomAdapter: typeof dom_adapter.DomAdapter,
_BrowserDomAdapter?: browserDomAdapter.BrowserDomAdapter,
BrowserDomAdapter: typeof browserDomAdapter.BrowserDomAdapter,
_BrowserGetTestability?: testability.BrowserGetTestability,
BrowserGetTestability: typeof testability.BrowserGetTestability,
getDOM: typeof dom_adapter.getDOM,
setRootDomAdapter: typeof dom_adapter.setRootDomAdapter,
_DomRootRenderer?: dom_renderer.DomRootRenderer,
DomRootRenderer: typeof dom_renderer.DomRootRenderer,
_DomRootRenderer_?: dom_renderer.DomRootRenderer,
DomRootRenderer_: typeof dom_renderer.DomRootRenderer_,
_DomSharedStylesHost?: shared_styles_host.DomSharedStylesHost,
DomSharedStylesHost: typeof shared_styles_host.DomSharedStylesHost,
_SharedStylesHost?: shared_styles_host.SharedStylesHost,
SharedStylesHost: typeof shared_styles_host.SharedStylesHost,
ELEMENT_PROBE_PROVIDERS: typeof ng_probe.ELEMENT_PROBE_PROVIDERS,
_DomEventsPlugin?: dom_events.DomEventsPlugin,
DomEventsPlugin: typeof dom_events.DomEventsPlugin, _KeyEventsPlugin?: key_events.KeyEventsPlugin,
KeyEventsPlugin: typeof key_events.KeyEventsPlugin,
_HammerGesturesPlugin?: hammer_gesture.HammerGesturesPlugin,
HammerGesturesPlugin: typeof hammer_gesture.HammerGesturesPlugin,
initDomAdapter: typeof browser.initDomAdapter,
INTERNAL_BROWSER_PLATFORM_PROVIDERS: typeof browser.INTERNAL_BROWSER_PLATFORM_PROVIDERS;
INTERNAL_BROWSER_PLATFORM_PROVIDERS: typeof browser.INTERNAL_BROWSER_PLATFORM_PROVIDERS,
BROWSER_SANITIZATION_PROVIDERS: typeof browser.BROWSER_SANITIZATION_PROVIDERS
} = {
BrowserPlatformLocation: location.BrowserPlatformLocation,
DomAdapter: dom_adapter.DomAdapter,
BrowserDomAdapter: browserDomAdapter.BrowserDomAdapter,
BrowserGetTestability: testability.BrowserGetTestability,
getDOM: dom_adapter.getDOM,
setRootDomAdapter: dom_adapter.setRootDomAdapter,
DomRootRenderer_: dom_renderer.DomRootRenderer_,
DomRootRenderer: dom_renderer.DomRootRenderer,
DomSharedStylesHost: shared_styles_host.DomSharedStylesHost,
SharedStylesHost: shared_styles_host.SharedStylesHost,
ELEMENT_PROBE_PROVIDERS: ng_probe.ELEMENT_PROBE_PROVIDERS,
DomEventsPlugin: dom_events.DomEventsPlugin,
KeyEventsPlugin: key_events.KeyEventsPlugin,
HammerGesturesPlugin: hammer_gesture.HammerGesturesPlugin,
initDomAdapter: browser.initDomAdapter,
INTERNAL_BROWSER_PLATFORM_PROVIDERS: browser.INTERNAL_BROWSER_PLATFORM_PROVIDERS
INTERNAL_BROWSER_PLATFORM_PROVIDERS: browser.INTERNAL_BROWSER_PLATFORM_PROVIDERS,
BROWSER_SANITIZATION_PROVIDERS: browser.BROWSER_SANITIZATION_PROVIDERS
};

View File

@ -10,12 +10,15 @@ import {__core_private__ as r} from '@angular/core';
export type RenderDebugInfo = typeof r._RenderDebugInfo;
export var RenderDebugInfo: typeof r.RenderDebugInfo = r.RenderDebugInfo;
export var ReflectionCapabilities: typeof r.ReflectionCapabilities = r.ReflectionCapabilities;
export var VIEW_ENCAPSULATION_VALUES: typeof r.VIEW_ENCAPSULATION_VALUES =
r.VIEW_ENCAPSULATION_VALUES;
export type DebugDomRootRenderer = typeof r._DebugDomRootRenderer;
export var DebugDomRootRenderer: typeof r.DebugDomRootRenderer = r.DebugDomRootRenderer;
export var reflector: typeof r.reflector = r.reflector;
export type NoOpAnimationPlayer = typeof r._NoOpAnimationPlayer;
export var NoOpAnimationPlayer: typeof r.NoOpAnimationPlayer = r.NoOpAnimationPlayer;
export type AnimationPlayer = typeof r._AnimationPlayer;

View File

@ -1,11 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
export const ON_WEB_WORKER = new OpaqueToken('WebWorker.onWebWorker');

View File

@ -1,183 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, Type} from '@angular/core';
import {EventEmitter} from '../../facade/async';
import {StringMapWrapper} from '../../facade/collection';
import {DateWrapper, StringWrapper, isPresent, print, stringify} from '../../facade/lang';
import {MessageBus} from './message_bus';
import {Serializer} from './serializer';
/**
* @experimental WebWorker support in Angular is experimental.
*/
export abstract class ClientMessageBrokerFactory {
/**
* Initializes the given channel and attaches a new {@link ClientMessageBroker} to it.
*/
abstract createMessageBroker(channel: string, runInZone?: boolean): ClientMessageBroker;
}
@Injectable()
export class ClientMessageBrokerFactory_ extends ClientMessageBrokerFactory {
/** @internal */
_serializer: Serializer;
constructor(private _messageBus: MessageBus, _serializer: Serializer) {
super();
this._serializer = _serializer;
}
/**
* Initializes the given channel and attaches a new {@link ClientMessageBroker} to it.
*/
createMessageBroker(channel: string, runInZone: boolean = true): ClientMessageBroker {
this._messageBus.initChannel(channel, runInZone);
return new ClientMessageBroker_(this._messageBus, this._serializer, channel);
}
}
/**
* @experimental WebWorker support in Angular is experimental.
*/
export abstract class ClientMessageBroker {
abstract runOnService(args: UiArguments, returnType: Type<any>): Promise<any>;
}
interface PromiseCompleter {
resolve: (result: any) => void;
reject: (err: any) => void;
}
export class ClientMessageBroker_ extends ClientMessageBroker {
private _pending: Map<string, PromiseCompleter> = new Map<string, PromiseCompleter>();
private _sink: EventEmitter<any>;
/** @internal */
public _serializer: Serializer;
constructor(
messageBus: MessageBus, _serializer: Serializer, public channel: any /** TODO #9100 */) {
super();
this._sink = messageBus.to(channel);
this._serializer = _serializer;
var source = messageBus.from(channel);
source.subscribe({next: (message: {[key: string]: any}) => this._handleMessage(message)});
}
private _generateMessageId(name: string): string {
var time: string = stringify(DateWrapper.toMillis(DateWrapper.now()));
var iteration: number = 0;
var id: string = name + time + stringify(iteration);
while (isPresent((this as any /** TODO #9100 */)._pending[id])) {
id = `${name}${time}${iteration}`;
iteration++;
}
return id;
}
runOnService(args: UiArguments, returnType: Type<any>): Promise<any> {
var fnArgs: any[] /** TODO #9100 */ = [];
if (isPresent(args.args)) {
args.args.forEach(argument => {
if (argument.type != null) {
fnArgs.push(this._serializer.serialize(argument.value, argument.type));
} else {
fnArgs.push(argument.value);
}
});
}
var promise: Promise<any>;
var id: string = null;
if (returnType != null) {
let completer: PromiseCompleter;
promise = new Promise((resolve, reject) => { completer = {resolve, reject}; });
id = this._generateMessageId(args.method);
this._pending.set(id, completer);
promise.catch((err) => {
print(err);
completer.reject(err);
});
promise = promise.then((value: any) => {
if (this._serializer == null) {
return value;
} else {
return this._serializer.deserialize(value, returnType);
}
});
} else {
promise = null;
}
// TODO(jteplitz602): Create a class for these messages so we don't keep using StringMap #3685
var message = {'method': args.method, 'args': fnArgs};
if (id != null) {
(message as any /** TODO #9100 */)['id'] = id;
}
this._sink.emit(message);
return promise;
}
private _handleMessage(message: {[key: string]: any}): void {
var data = new MessageData(message);
// TODO(jteplitz602): replace these strings with messaging constants #3685
if (StringWrapper.equals(data.type, 'result') || StringWrapper.equals(data.type, 'error')) {
var id = data.id;
if (this._pending.has(id)) {
if (StringWrapper.equals(data.type, 'result')) {
this._pending.get(id).resolve(data.value);
} else {
this._pending.get(id).reject(data.value);
}
this._pending.delete(id);
}
}
}
}
class MessageData {
type: string;
value: any;
id: string;
constructor(data: {[key: string]: any}) {
this.type = StringMapWrapper.get(data, 'type');
this.id = this._getValueIfPresent(data, 'id');
this.value = this._getValueIfPresent(data, 'value');
}
/**
* Returns the value from the StringMap if present. Otherwise returns null
* @internal
*/
_getValueIfPresent(data: {[key: string]: any}, key: string) {
if (StringMapWrapper.contains(data, key)) {
return StringMapWrapper.get(data, key);
} else {
return null;
}
}
}
/**
* @experimental WebWorker support in Angular is experimental.
*/
export class FnArg {
constructor(public value: any /** TODO #9100 */, public type: Type<any>) {}
}
/**
* @experimental WebWorker support in Angular is experimental.
*/
export class UiArguments {
constructor(public method: string, public args?: FnArg[]) {}
}

View File

@ -1,104 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {NgZone} from '@angular/core';
import {EventEmitter} from '../../facade/async';
/**
* Message Bus is a low level API used to communicate between the UI and the background.
* Communication is based on a channel abstraction. Messages published in a
* given channel to one MessageBusSink are received on the same channel
* by the corresponding MessageBusSource.
*
* @experimental WebWorker support in Angular is currenlty experimental.
*/
export abstract class MessageBus implements MessageBusSource, MessageBusSink {
/**
* Sets up a new channel on the MessageBus.
* MUST be called before calling from or to on the channel.
* If runInZone is true then the source will emit events inside the angular zone
* and the sink will buffer messages and send only once the zone exits.
* if runInZone is false then the source will emit events inside the global zone
* and the sink will send messages immediately.
*/
abstract initChannel(channel: string, runInZone?: boolean): void;
/**
* Assigns this bus to the given zone.
* Any callbacks attached to channels where runInZone was set to true on initialization
* will be executed in the given zone.
*/
abstract attachToZone(zone: NgZone): void;
/**
* Returns an {@link EventEmitter} that emits every time a message
* is received on the given channel.
*/
abstract from(channel: string): EventEmitter<any>;
/**
* Returns an {@link EventEmitter} for the given channel
* To publish methods to that channel just call next on the returned emitter
*/
abstract to(channel: string): EventEmitter<any>;
}
/**
* @experimental WebWorker support in Angular is currenlty experimental.
*/
export interface MessageBusSource {
/**
* Sets up a new channel on the MessageBusSource.
* MUST be called before calling from on the channel.
* If runInZone is true then the source will emit events inside the angular zone.
* if runInZone is false then the source will emit events inside the global zone.
*/
initChannel(channel: string, runInZone: boolean): void;
/**
* Assigns this source to the given zone.
* Any channels which are initialized with runInZone set to true will emit events that will be
* executed within the given zone.
*/
attachToZone(zone: NgZone): void;
/**
* Returns an {@link EventEmitter} that emits every time a message
* is received on the given channel.
*/
from(channel: string): EventEmitter<any>;
}
/**
* @experimental WebWorker support in Angular is currenlty experimental.
*/
export interface MessageBusSink {
/**
* Sets up a new channel on the MessageBusSink.
* MUST be called before calling to on the channel.
* If runInZone is true the sink will buffer messages and send only once the zone exits.
* if runInZone is false the sink will send messages immediatly.
*/
initChannel(channel: string, runInZone: boolean): void;
/**
* Assigns this sink to the given zone.
* Any channels which are initialized with runInZone set to true will wait for the given zone
* to exit before sending messages.
*/
attachToZone(zone: NgZone): void;
/**
* Returns an {@link EventEmitter} for the given channel
* To publish methods to that channel just call next on the returned emitter
*/
to(channel: string): EventEmitter<any>;
}

View File

@ -1,15 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* All channels used by angular's WebWorker components are listed here.
* You should not use these channels in your application code.
*/
export const RENDERER_CHANNEL = 'ng-Renderer';
export const EVENT_CHANNEL = 'ng-Events';
export const ROUTER_CHANNEL = 'ng-Router';

View File

@ -1,155 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, NgZone} from '@angular/core';
import {EventEmitter} from '../../facade/async';
import {StringMapWrapper} from '../../facade/collection';
import {MessageBus, MessageBusSink, MessageBusSource} from './message_bus';
// TODO(jteplitz602) Replace this with the definition in lib.webworker.d.ts(#3492)
export interface PostMessageTarget {
postMessage: (message: any, transfer?: [ArrayBuffer]) => void;
}
export class PostMessageBusSink implements MessageBusSink {
private _zone: NgZone;
private _channels: {[key: string]: _Channel} = StringMapWrapper.create();
private _messageBuffer: Array<Object> = [];
constructor(private _postMessageTarget: PostMessageTarget) {}
attachToZone(zone: NgZone): void {
this._zone = zone;
this._zone.runOutsideAngular(
() => { this._zone.onStable.subscribe({next: () => { this._handleOnEventDone(); }}); });
}
initChannel(channel: string, runInZone: boolean = true): void {
if (StringMapWrapper.contains(this._channels, channel)) {
throw new Error(`${channel} has already been initialized`);
}
var emitter = new EventEmitter(false);
var channelInfo = new _Channel(emitter, runInZone);
this._channels[channel] = channelInfo;
emitter.subscribe((data: Object) => {
var message = {channel: channel, message: data};
if (runInZone) {
this._messageBuffer.push(message);
} else {
this._sendMessages([message]);
}
});
}
to(channel: string): EventEmitter<any> {
if (StringMapWrapper.contains(this._channels, channel)) {
return this._channels[channel].emitter;
} else {
throw new Error(`${channel} is not set up. Did you forget to call initChannel?`);
}
}
private _handleOnEventDone() {
if (this._messageBuffer.length > 0) {
this._sendMessages(this._messageBuffer);
this._messageBuffer = [];
}
}
private _sendMessages(messages: Array<Object>) { this._postMessageTarget.postMessage(messages); }
}
export class PostMessageBusSource implements MessageBusSource {
private _zone: NgZone;
private _channels: {[key: string]: _Channel} = StringMapWrapper.create();
constructor(eventTarget?: EventTarget) {
if (eventTarget) {
eventTarget.addEventListener('message', (ev: MessageEvent) => this._handleMessages(ev));
} else {
// if no eventTarget is given we assume we're in a WebWorker and listen on the global scope
const workerScope = <EventTarget>self;
workerScope.addEventListener('message', (ev: MessageEvent) => this._handleMessages(ev));
}
}
attachToZone(zone: NgZone) { this._zone = zone; }
initChannel(channel: string, runInZone: boolean = true) {
if (StringMapWrapper.contains(this._channels, channel)) {
throw new Error(`${channel} has already been initialized`);
}
var emitter = new EventEmitter(false);
var channelInfo = new _Channel(emitter, runInZone);
this._channels[channel] = channelInfo;
}
from(channel: string): EventEmitter<any> {
if (StringMapWrapper.contains(this._channels, channel)) {
return this._channels[channel].emitter;
} else {
throw new Error(`${channel} is not set up. Did you forget to call initChannel?`);
}
}
private _handleMessages(ev: MessageEvent): void {
var messages = ev.data;
for (var i = 0; i < messages.length; i++) {
this._handleMessage(messages[i]);
}
}
private _handleMessage(data: any): void {
var channel = data.channel;
if (StringMapWrapper.contains(this._channels, channel)) {
var channelInfo = this._channels[channel];
if (channelInfo.runInZone) {
this._zone.run(() => { channelInfo.emitter.emit(data.message); });
} else {
channelInfo.emitter.emit(data.message);
}
}
}
}
/**
* A TypeScript implementation of {@link MessageBus} for communicating via JavaScript's
* postMessage API.
*/
@Injectable()
export class PostMessageBus implements MessageBus {
constructor(public sink: PostMessageBusSink, public source: PostMessageBusSource) {}
attachToZone(zone: NgZone): void {
this.source.attachToZone(zone);
this.sink.attachToZone(zone);
}
initChannel(channel: string, runInZone: boolean = true): void {
this.source.initChannel(channel, runInZone);
this.sink.initChannel(channel, runInZone);
}
from(channel: string): EventEmitter<any> { return this.source.from(channel); }
to(channel: string): EventEmitter<any> { return this.sink.to(channel); }
}
/**
* Helper class that wraps a channel's {@link EventEmitter} and
* keeps track of if it should run in the zone.
*/
class _Channel {
constructor(public emitter: EventEmitter<any>, public runInZone: boolean) {}
}

View File

@ -1,53 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable} from '@angular/core';
@Injectable()
export class RenderStore {
private _nextIndex: number = 0;
private _lookupById: Map<number, any>;
private _lookupByObject: Map<any, number>;
constructor() {
this._lookupById = new Map<number, any>();
this._lookupByObject = new Map<any, number>();
}
allocateId(): number { return this._nextIndex++; }
store(obj: any, id: number): void {
this._lookupById.set(id, obj);
this._lookupByObject.set(obj, id);
}
remove(obj: any): void {
var index = this._lookupByObject.get(obj);
this._lookupByObject.delete(obj);
this._lookupById.delete(index);
}
deserialize(id: number): any {
if (id == null) {
return null;
}
if (!this._lookupById.has(id)) {
return null;
}
return this._lookupById.get(id);
}
serialize(obj: any): number {
if (obj == null) {
return null;
}
return this._lookupByObject.get(obj);
}
}

View File

@ -1,16 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// This file contains interface versions of browser types that can be serialized to Plain Old
// JavaScript Objects
export class LocationType {
constructor(
public href: string, public protocol: string, public host: string, public hostname: string,
public port: string, public pathname: string, public search: string, public hash: string,
public origin: string) {}
}

View File

@ -1,119 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, RenderComponentType, Type, ViewEncapsulation} from '@angular/core';
import {Map, MapWrapper, StringMapWrapper} from '../../facade/collection';
import {isArray, isPresent, serializeEnum} from '../../facade/lang';
import {VIEW_ENCAPSULATION_VALUES} from '../../private_import_core';
import {RenderStore} from './render_store';
import {LocationType} from './serialized_types';
// PRIMITIVE is any type that does not need to be serialized (string, number, boolean)
// We set it to String so that it is considered a Type.
/**
* @experimental WebWorker support in Angular is currently experimental.
*/
export const PRIMITIVE: Type<any> = String;
@Injectable()
export class Serializer {
constructor(private _renderStore: RenderStore) {}
serialize(obj: any, type: any): Object {
if (!isPresent(obj)) {
return null;
}
if (isArray(obj)) {
return (<any[]>obj).map(v => this.serialize(v, type));
}
if (type == PRIMITIVE) {
return obj;
}
if (type == RenderStoreObject) {
return this._renderStore.serialize(obj);
} else if (type === RenderComponentType) {
return this._serializeRenderComponentType(obj);
} else if (type === ViewEncapsulation) {
return serializeEnum(obj);
} else if (type === LocationType) {
return this._serializeLocation(obj);
} else {
throw new Error('No serializer for ' + type.toString());
}
}
deserialize(map: any, type: any, data?: any): any {
if (!isPresent(map)) {
return null;
}
if (isArray(map)) {
var obj: any[] = [];
(<any[]>map).forEach(val => obj.push(this.deserialize(val, type, data)));
return obj;
}
if (type == PRIMITIVE) {
return map;
}
if (type == RenderStoreObject) {
return this._renderStore.deserialize(map);
} else if (type === RenderComponentType) {
return this._deserializeRenderComponentType(map);
} else if (type === ViewEncapsulation) {
return VIEW_ENCAPSULATION_VALUES[map];
} else if (type === LocationType) {
return this._deserializeLocation(map);
} else {
throw new Error('No deserializer for ' + type.toString());
}
}
private _serializeLocation(loc: LocationType): Object {
return {
'href': loc.href,
'protocol': loc.protocol,
'host': loc.host,
'hostname': loc.hostname,
'port': loc.port,
'pathname': loc.pathname,
'search': loc.search,
'hash': loc.hash,
'origin': loc.origin
};
}
private _deserializeLocation(loc: {[key: string]: any}): LocationType {
return new LocationType(
loc['href'], loc['protocol'], loc['host'], loc['hostname'], loc['port'], loc['pathname'],
loc['search'], loc['hash'], loc['origin']);
}
private _serializeRenderComponentType(obj: RenderComponentType): Object {
return {
'id': obj.id,
'templateUrl': obj.templateUrl,
'slotCount': obj.slotCount,
'encapsulation': this.serialize(obj.encapsulation, ViewEncapsulation),
'styles': this.serialize(obj.styles, PRIMITIVE)
};
}
private _deserializeRenderComponentType(map: {[key: string]: any}): RenderComponentType {
return new RenderComponentType(
map['id'], map['templateUrl'], map['slotCount'],
this.deserialize(map['encapsulation'], ViewEncapsulation),
this.deserialize(map['styles'], PRIMITIVE), {});
}
}
export class RenderStoreObject {}

View File

@ -1,118 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, Type} from '@angular/core';
import {EventEmitter} from '../../facade/async';
import {ListWrapper, Map} from '../../facade/collection';
import {FunctionWrapper, isPresent} from '../../facade/lang';
import {MessageBus} from '../shared/message_bus';
import {Serializer} from '../shared/serializer';
/**
* @experimental WebWorker support in Angular is currently experimental.
*/
export abstract class ServiceMessageBrokerFactory {
/**
* Initializes the given channel and attaches a new {@link ServiceMessageBroker} to it.
*/
abstract createMessageBroker(channel: string, runInZone?: boolean): ServiceMessageBroker;
}
@Injectable()
export class ServiceMessageBrokerFactory_ extends ServiceMessageBrokerFactory {
/** @internal */
_serializer: Serializer;
constructor(private _messageBus: MessageBus, _serializer: Serializer) {
super();
this._serializer = _serializer;
}
createMessageBroker(channel: string, runInZone: boolean = true): ServiceMessageBroker {
this._messageBus.initChannel(channel, runInZone);
return new ServiceMessageBroker_(this._messageBus, this._serializer, channel);
}
}
/**
* Helper class for UIComponents that allows components to register methods.
* If a registered method message is received from the broker on the worker,
* the UIMessageBroker deserializes its arguments and calls the registered method.
* If that method returns a promise, the UIMessageBroker returns the result to the worker.
*
* @experimental WebWorker support in Angular is currently experimental.
*/
export abstract class ServiceMessageBroker {
abstract registerMethod(
methodName: string, signature: Type<any>[], method: Function, returnType?: Type<any>): void;
}
export class ServiceMessageBroker_ extends ServiceMessageBroker {
private _sink: EventEmitter<any>;
private _methods: Map<string, Function> = new Map<string, Function>();
constructor(
messageBus: MessageBus, private _serializer: Serializer,
public channel: any /** TODO #9100 */) {
super();
this._sink = messageBus.to(channel);
var source = messageBus.from(channel);
source.subscribe({next: (message: any) => this._handleMessage(message)});
}
registerMethod(
methodName: string, signature: Type<any>[], method: (..._: any[]) => Promise<any>| void,
returnType?: Type<any>): void {
this._methods.set(methodName, (message: ReceivedMessage) => {
var serializedArgs = message.args;
let numArgs = signature === null ? 0 : signature.length;
var deserializedArgs: any[] = ListWrapper.createFixedSize(numArgs);
for (var i = 0; i < numArgs; i++) {
var serializedArg = serializedArgs[i];
deserializedArgs[i] = this._serializer.deserialize(serializedArg, signature[i]);
}
var promise = FunctionWrapper.apply(method, deserializedArgs);
if (isPresent(returnType) && isPresent(promise)) {
this._wrapWebWorkerPromise(message.id, promise, returnType);
}
});
}
private _handleMessage(map: {[key: string]: any}): void {
var message = new ReceivedMessage(map);
if (this._methods.has(message.method)) {
this._methods.get(message.method)(message);
}
}
private _wrapWebWorkerPromise(id: string, promise: Promise<any>, type: Type<any>): void {
promise.then((result: any) => {
this._sink.emit(
{'type': 'result', 'value': this._serializer.serialize(result, type), 'id': id});
});
}
}
/**
* @experimental WebWorker support in Angular is currently experimental.
*/
export class ReceivedMessage {
method: string;
args: any[];
id: string;
type: string;
constructor(data: {[key: string]: any}) {
this.method = data['method'];
this.args = data['args'];
this.id = data['id'];
this.type = data['type'];
}
}

View File

@ -1,112 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {EventEmitter} from '../../facade/async';
import {RenderStoreObject, Serializer} from '../shared/serializer';
import {serializeEventWithTarget, serializeGenericEvent, serializeKeyboardEvent, serializeMouseEvent, serializeTransitionEvent} from './event_serializer';
export class EventDispatcher {
constructor(private _sink: EventEmitter<any>, private _serializer: Serializer) {}
dispatchRenderEvent(element: any, eventTarget: string, eventName: string, event: any): boolean {
var serializedEvent: any /** TODO #9100 */;
// TODO (jteplitz602): support custom events #3350
switch (event.type) {
case 'click':
case 'mouseup':
case 'mousedown':
case 'dblclick':
case 'contextmenu':
case 'mouseenter':
case 'mouseleave':
case 'mousemove':
case 'mouseout':
case 'mouseover':
case 'show':
serializedEvent = serializeMouseEvent(event);
break;
case 'keydown':
case 'keypress':
case 'keyup':
serializedEvent = serializeKeyboardEvent(event);
break;
case 'input':
case 'change':
case 'blur':
serializedEvent = serializeEventWithTarget(event);
break;
case 'abort':
case 'afterprint':
case 'beforeprint':
case 'cached':
case 'canplay':
case 'canplaythrough':
case 'chargingchange':
case 'chargingtimechange':
case 'close':
case 'dischargingtimechange':
case 'DOMContentLoaded':
case 'downloading':
case 'durationchange':
case 'emptied':
case 'ended':
case 'error':
case 'fullscreenchange':
case 'fullscreenerror':
case 'invalid':
case 'languagechange':
case 'levelfchange':
case 'loadeddata':
case 'loadedmetadata':
case 'obsolete':
case 'offline':
case 'online':
case 'open':
case 'orientatoinchange':
case 'pause':
case 'pointerlockchange':
case 'pointerlockerror':
case 'play':
case 'playing':
case 'ratechange':
case 'readystatechange':
case 'reset':
case 'scroll':
case 'seeked':
case 'seeking':
case 'stalled':
case 'submit':
case 'success':
case 'suspend':
case 'timeupdate':
case 'updateready':
case 'visibilitychange':
case 'volumechange':
case 'waiting':
serializedEvent = serializeGenericEvent(event);
break;
case 'transitionend':
serializedEvent = serializeTransitionEvent(event);
break;
default:
throw new Error(eventName + ' not supported on WebWorkers');
}
this._sink.emit({
'element': this._serializer.serialize(element, RenderStoreObject),
'eventName': eventName,
'eventTarget': eventTarget,
'event': serializedEvent
});
// TODO(kegluneq): Eventually, we want the user to indicate from the UI side whether the event
// should be canceled, but for now just call `preventDefault` on the original DOM event.
return false;
}
}

View File

@ -1,73 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Set} from '../../facade/collection';
import {isPresent} from '../../facade/lang';
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'
];
const TRANSITION_EVENT_PROPERTIES = ['propertyName', 'elapsedTime', 'pseudoElement'];
const EVENT_PROPERTIES = ['type', 'bubbles', 'cancelable'];
const NODES_WITH_VALUE = new Set(
['input', 'select', 'option', 'button', 'li', 'meter', 'progress', 'param', 'textarea']);
export function serializeGenericEvent(e: Event): {[key: string]: any} {
return serializeEvent(e, EVENT_PROPERTIES);
}
// TODO(jteplitz602): Allow users to specify the properties they need rather than always
// adding value and files #3374
export function serializeEventWithTarget(e: Event): {[key: string]: any} {
var serializedEvent = serializeEvent(e, EVENT_PROPERTIES);
return addTarget(e, serializedEvent);
}
export function serializeMouseEvent(e: MouseEvent): {[key: string]: any} {
return serializeEvent(e, MOUSE_EVENT_PROPERTIES);
}
export function serializeKeyboardEvent(e: KeyboardEvent): {[key: string]: any} {
var serializedEvent = serializeEvent(e, KEYBOARD_EVENT_PROPERTIES);
return addTarget(e, serializedEvent);
}
export function serializeTransitionEvent(e: TransitionEvent): {[key: string]: any} {
var serializedEvent = serializeEvent(e, TRANSITION_EVENT_PROPERTIES);
return addTarget(e, serializedEvent);
}
// TODO(jteplitz602): #3374. See above.
function addTarget(e: Event, serializedEvent: {[key: string]: any}): {[key: string]: any} {
if (NODES_WITH_VALUE.has((<HTMLElement>e.target).tagName.toLowerCase())) {
var target = <HTMLInputElement>e.target;
serializedEvent['target'] = {'value': target.value};
if (isPresent(target.files)) {
serializedEvent['target']['files'] = target.files;
}
}
return serializedEvent;
}
function serializeEvent(e: any, properties: string[]): {[key: string]: any} {
var serialized = {};
for (var i = 0; i < properties.length; i++) {
var prop = properties[i];
(serialized as any /** TODO #9100 */)[prop] = e[prop];
}
return serialized;
}

View File

@ -1,33 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, NgZone, PLATFORM_INITIALIZER} from '@angular/core';
import {BrowserPlatformLocation} from '../../browser/location/browser_platform_location';
import {MessageBasedPlatformLocation} from './platform_location';
/**
* A list of {@link Provider}s. To use the router in a Worker enabled application you must
* include these providers when setting up the render thread.
* @experimental
*/
export const WORKER_UI_LOCATION_PROVIDERS = [
MessageBasedPlatformLocation, BrowserPlatformLocation,
{provide: PLATFORM_INITIALIZER, useFactory: initUiLocation, multi: true, deps: [Injector]}
];
function initUiLocation(injector: Injector): () => void {
return () => {
let zone = injector.get(NgZone);
zone.runGuarded(() => injector.get(MessageBasedPlatformLocation).start());
};
}

View File

@ -1,68 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {LocationChangeListener} from '@angular/common';
import {Injectable} from '@angular/core';
import {BrowserPlatformLocation} from '../../browser/location/browser_platform_location';
import {EventEmitter} from '../../facade/async';
import {FunctionWrapper} from '../../facade/lang';
import {MessageBus} from '../shared/message_bus';
import {ROUTER_CHANNEL} from '../shared/messaging_api';
import {LocationType} from '../shared/serialized_types';
import {PRIMITIVE, Serializer} from '../shared/serializer';
import {ServiceMessageBroker, ServiceMessageBrokerFactory} from '../shared/service_message_broker';
@Injectable()
export class MessageBasedPlatformLocation {
private _channelSink: EventEmitter<Object>;
private _broker: ServiceMessageBroker;
constructor(
private _brokerFactory: ServiceMessageBrokerFactory,
private _platformLocation: BrowserPlatformLocation, bus: MessageBus,
private _serializer: Serializer) {
this._platformLocation.onPopState(
<LocationChangeListener>FunctionWrapper.bind(this._sendUrlChangeEvent, this));
this._platformLocation.onHashChange(
<LocationChangeListener>FunctionWrapper.bind(this._sendUrlChangeEvent, this));
this._broker = this._brokerFactory.createMessageBroker(ROUTER_CHANNEL);
this._channelSink = bus.to(ROUTER_CHANNEL);
}
start(): void {
this._broker.registerMethod(
'getLocation', null, FunctionWrapper.bind(this._getLocation, this), LocationType);
this._broker.registerMethod(
'setPathname', [PRIMITIVE], FunctionWrapper.bind(this._setPathname, this));
this._broker.registerMethod(
'pushState', [PRIMITIVE, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._platformLocation.pushState, this._platformLocation));
this._broker.registerMethod(
'replaceState', [PRIMITIVE, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._platformLocation.replaceState, this._platformLocation));
this._broker.registerMethod(
'forward', null,
FunctionWrapper.bind(this._platformLocation.forward, this._platformLocation));
this._broker.registerMethod(
'back', null, FunctionWrapper.bind(this._platformLocation.back, this._platformLocation));
}
private _getLocation(): Promise<Location> {
return Promise.resolve(this._platformLocation.location);
}
private _sendUrlChangeEvent(e: Event): void {
let loc = this._serializer.serialize(this._platformLocation.location, LocationType);
let serializedEvent = {'type': e.type};
this._channelSink.emit({'event': serializedEvent, 'location': loc});
}
private _setPathname(pathname: string): void { this._platformLocation.pathname = pathname; }
}

View File

@ -1,195 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, RenderComponentType, Renderer, RootRenderer} from '@angular/core';
import {FunctionWrapper} from '../../facade/lang';
import {MessageBus} from '../shared/message_bus';
import {EVENT_CHANNEL, RENDERER_CHANNEL} from '../shared/messaging_api';
import {RenderStore} from '../shared/render_store';
import {PRIMITIVE, RenderStoreObject, Serializer} from '../shared/serializer';
import {ServiceMessageBrokerFactory} from '../shared/service_message_broker';
import {EventDispatcher} from '../ui/event_dispatcher';
@Injectable()
export class MessageBasedRenderer {
private _eventDispatcher: EventDispatcher;
constructor(
private _brokerFactory: ServiceMessageBrokerFactory, private _bus: MessageBus,
private _serializer: Serializer, private _renderStore: RenderStore,
private _rootRenderer: RootRenderer) {}
start(): void {
var broker = this._brokerFactory.createMessageBroker(RENDERER_CHANNEL);
this._bus.initChannel(EVENT_CHANNEL);
this._eventDispatcher = new EventDispatcher(this._bus.to(EVENT_CHANNEL), this._serializer);
broker.registerMethod(
'renderComponent', [RenderComponentType, PRIMITIVE],
FunctionWrapper.bind(this._renderComponent, this));
broker.registerMethod(
'selectRootElement', [RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._selectRootElement, this));
broker.registerMethod(
'createElement', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._createElement, this));
broker.registerMethod(
'createViewRoot', [RenderStoreObject, RenderStoreObject, PRIMITIVE],
FunctionWrapper.bind(this._createViewRoot, this));
broker.registerMethod(
'createTemplateAnchor', [RenderStoreObject, RenderStoreObject, PRIMITIVE],
FunctionWrapper.bind(this._createTemplateAnchor, this));
broker.registerMethod(
'createText', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._createText, this));
broker.registerMethod(
'projectNodes', [RenderStoreObject, RenderStoreObject, RenderStoreObject],
FunctionWrapper.bind(this._projectNodes, this));
broker.registerMethod(
'attachViewAfter', [RenderStoreObject, RenderStoreObject, RenderStoreObject],
FunctionWrapper.bind(this._attachViewAfter, this));
broker.registerMethod(
'detachView', [RenderStoreObject, RenderStoreObject],
FunctionWrapper.bind(this._detachView, this));
broker.registerMethod(
'destroyView', [RenderStoreObject, RenderStoreObject, RenderStoreObject],
FunctionWrapper.bind(this._destroyView, this));
broker.registerMethod(
'setElementProperty', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._setElementProperty, this));
broker.registerMethod(
'setElementAttribute', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._setElementAttribute, this));
broker.registerMethod(
'setBindingDebugInfo', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._setBindingDebugInfo, this));
broker.registerMethod(
'setElementClass', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._setElementClass, this));
broker.registerMethod(
'setElementStyle', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._setElementStyle, this));
broker.registerMethod(
'invokeElementMethod', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._invokeElementMethod, this));
broker.registerMethod(
'setText', [RenderStoreObject, RenderStoreObject, PRIMITIVE],
FunctionWrapper.bind(this._setText, this));
broker.registerMethod(
'listen', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._listen, this));
broker.registerMethod(
'listenGlobal', [RenderStoreObject, PRIMITIVE, PRIMITIVE, PRIMITIVE],
FunctionWrapper.bind(this._listenGlobal, this));
broker.registerMethod(
'listenDone', [RenderStoreObject, RenderStoreObject],
FunctionWrapper.bind(this._listenDone, this));
}
private _renderComponent(renderComponentType: RenderComponentType, rendererId: number) {
var renderer = this._rootRenderer.renderComponent(renderComponentType);
this._renderStore.store(renderer, rendererId);
}
private _selectRootElement(renderer: Renderer, selector: string, elId: number) {
this._renderStore.store(renderer.selectRootElement(selector, null), elId);
}
private _createElement(renderer: Renderer, parentElement: any, name: string, elId: number) {
this._renderStore.store(renderer.createElement(parentElement, name, null), elId);
}
private _createViewRoot(renderer: Renderer, hostElement: any, elId: number) {
var viewRoot = renderer.createViewRoot(hostElement);
if (this._renderStore.serialize(hostElement) !== elId) {
this._renderStore.store(viewRoot, elId);
}
}
private _createTemplateAnchor(renderer: Renderer, parentElement: any, elId: number) {
this._renderStore.store(renderer.createTemplateAnchor(parentElement, null), elId);
}
private _createText(renderer: Renderer, parentElement: any, value: string, elId: number) {
this._renderStore.store(renderer.createText(parentElement, value, null), elId);
}
private _projectNodes(renderer: Renderer, parentElement: any, nodes: any[]) {
renderer.projectNodes(parentElement, nodes);
}
private _attachViewAfter(renderer: Renderer, node: any, viewRootNodes: any[]) {
renderer.attachViewAfter(node, viewRootNodes);
}
private _detachView(renderer: Renderer, viewRootNodes: any[]) {
renderer.detachView(viewRootNodes);
}
private _destroyView(renderer: Renderer, hostElement: any, viewAllNodes: any[]) {
renderer.destroyView(hostElement, viewAllNodes);
for (var i = 0; i < viewAllNodes.length; i++) {
this._renderStore.remove(viewAllNodes[i]);
}
}
private _setElementProperty(
renderer: Renderer, renderElement: any, propertyName: string, propertyValue: any) {
renderer.setElementProperty(renderElement, propertyName, propertyValue);
}
private _setElementAttribute(
renderer: Renderer, renderElement: any, attributeName: string, attributeValue: string) {
renderer.setElementAttribute(renderElement, attributeName, attributeValue);
}
private _setBindingDebugInfo(
renderer: Renderer, renderElement: any, propertyName: string, propertyValue: string) {
renderer.setBindingDebugInfo(renderElement, propertyName, propertyValue);
}
private _setElementClass(
renderer: Renderer, renderElement: any, className: string, isAdd: boolean) {
renderer.setElementClass(renderElement, className, isAdd);
}
private _setElementStyle(
renderer: Renderer, renderElement: any, styleName: string, styleValue: string) {
renderer.setElementStyle(renderElement, styleName, styleValue);
}
private _invokeElementMethod(
renderer: Renderer, renderElement: any, methodName: string, args: any[]) {
renderer.invokeElementMethod(renderElement, methodName, args);
}
private _setText(renderer: Renderer, renderNode: any, text: string) {
renderer.setText(renderNode, text);
}
private _listen(renderer: Renderer, renderElement: any, eventName: string, unlistenId: number) {
var unregisterCallback = renderer.listen(
renderElement, eventName,
(event: any /** TODO #9100 */) =>
this._eventDispatcher.dispatchRenderEvent(renderElement, null, eventName, event));
this._renderStore.store(unregisterCallback, unlistenId);
}
private _listenGlobal(
renderer: Renderer, eventTarget: string, eventName: string, unlistenId: number) {
var unregisterCallback = renderer.listenGlobal(
eventTarget, eventName,
(event: any /** TODO #9100 */) =>
this._eventDispatcher.dispatchRenderEvent(null, eventTarget, eventName, event));
this._renderStore.store(unregisterCallback, unlistenId);
}
private _listenDone(renderer: Renderer, unlistenCallback: Function) { unlistenCallback(); }
}

View File

@ -1,14 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// no deserialization is necessary in TS.
// This is only here to match dart interface
export function deserializeGenericEvent(serializedEvent: {[key: string]: any}):
{[key: string]: any} {
return serializedEvent;
}

View File

@ -1,32 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {PlatformLocation} from '@angular/common';
import {APP_INITIALIZER, NgZone} from '@angular/core';
import {WebWorkerPlatformLocation} from './platform_location';
/**
* Those providers should be added when the router is used in a worker context in addition to the
* {@link ROUTER_PROVIDERS} and after them.
* @experimental
*/
export const WORKER_APP_LOCATION_PROVIDERS = [
{provide: PlatformLocation, useClass: WebWorkerPlatformLocation}, {
provide: APP_INITIALIZER,
useFactory: appInitFnFactory,
multi: true,
deps: [PlatformLocation, NgZone]
}
];
function appInitFnFactory(platformLocation: WebWorkerPlatformLocation, zone: NgZone): () =>
Promise<boolean> {
return () => { return zone.runGuarded(() => platformLocation.init()); };
}

View File

@ -1,141 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {LocationChangeListener, PlatformLocation} from '@angular/common';
import {Injectable} from '@angular/core';
import {EventEmitter} from '../../facade/async';
import {StringMapWrapper} from '../../facade/collection';
import {StringWrapper} from '../../facade/lang';
import {ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments} from '../shared/client_message_broker';
import {MessageBus} from '../shared/message_bus';
import {ROUTER_CHANNEL} from '../shared/messaging_api';
import {LocationType} from '../shared/serialized_types';
import {PRIMITIVE, Serializer} from '../shared/serializer';
import {deserializeGenericEvent} from './event_deserializer';
@Injectable()
export class WebWorkerPlatformLocation extends PlatformLocation {
private _broker: ClientMessageBroker;
private _popStateListeners: Array<Function> = [];
private _hashChangeListeners: Array<Function> = [];
private _location: LocationType = null;
private _channelSource: EventEmitter<Object>;
constructor(
brokerFactory: ClientMessageBrokerFactory, bus: MessageBus, private _serializer: Serializer) {
super();
this._broker = brokerFactory.createMessageBroker(ROUTER_CHANNEL);
this._channelSource = bus.from(ROUTER_CHANNEL);
this._channelSource.subscribe({
next: (msg: {[key: string]: any}) => {
var listeners: Array<Function> = null;
if (StringMapWrapper.contains(msg, 'event')) {
let type: string = msg['event']['type'];
if (StringWrapper.equals(type, 'popstate')) {
listeners = this._popStateListeners;
} else if (StringWrapper.equals(type, 'hashchange')) {
listeners = this._hashChangeListeners;
}
if (listeners !== null) {
let e = deserializeGenericEvent(msg['event']);
// There was a popState or hashChange event, so the location object thas been updated
this._location = this._serializer.deserialize(msg['location'], LocationType);
listeners.forEach((fn: Function) => fn(e));
}
}
}
});
}
/** @internal **/
init(): Promise<boolean> {
var args: UiArguments = new UiArguments('getLocation');
var locationPromise: Promise<LocationType> = this._broker.runOnService(args, LocationType);
return locationPromise.then(
(val: LocationType):
boolean => {
this._location = val;
return true;
},
(err): boolean => { throw new Error(err); });
}
getBaseHrefFromDOM(): string {
throw new Error(
'Attempt to get base href from DOM from WebWorker. You must either provide a value for the APP_BASE_HREF token through DI or use the hash location strategy.');
}
onPopState(fn: LocationChangeListener): void { this._popStateListeners.push(fn); }
onHashChange(fn: LocationChangeListener): void { this._hashChangeListeners.push(fn); }
get pathname(): string {
if (this._location === null) {
return null;
}
return this._location.pathname;
}
get search(): string {
if (this._location === null) {
return null;
}
return this._location.search;
}
get hash(): string {
if (this._location === null) {
return null;
}
return this._location.hash;
}
set pathname(newPath: string) {
if (this._location === null) {
throw new Error('Attempt to set pathname before value is obtained from UI');
}
this._location.pathname = newPath;
var fnArgs = [new FnArg(newPath, PRIMITIVE)];
var args = new UiArguments('setPathname', fnArgs);
this._broker.runOnService(args, null);
}
pushState(state: any, title: string, url: string): void {
var fnArgs =
[new FnArg(state, PRIMITIVE), new FnArg(title, PRIMITIVE), new FnArg(url, PRIMITIVE)];
var args = new UiArguments('pushState', fnArgs);
this._broker.runOnService(args, null);
}
replaceState(state: any, title: string, url: string): void {
var fnArgs =
[new FnArg(state, PRIMITIVE), new FnArg(title, PRIMITIVE), new FnArg(url, PRIMITIVE)];
var args = new UiArguments('replaceState', fnArgs);
this._broker.runOnService(args, null);
}
forward(): void {
var args = new UiArguments('forward');
this._broker.runOnService(args, null);
}
back(): void {
var args = new UiArguments('back');
this._broker.runOnService(args, null);
}
}

View File

@ -1,275 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, RenderComponentType, Renderer, RootRenderer, ViewEncapsulation} from '@angular/core';
import {ListWrapper} from '../../facade/collection';
import {isBlank, isPresent} from '../../facade/lang';
import {AnimationKeyframe, AnimationPlayer, AnimationStyles, RenderDebugInfo} from '../../private_import_core';
import {ClientMessageBrokerFactory, FnArg, UiArguments} from '../shared/client_message_broker';
import {MessageBus} from '../shared/message_bus';
import {EVENT_CHANNEL, RENDERER_CHANNEL} from '../shared/messaging_api';
import {RenderStore} from '../shared/render_store';
import {RenderStoreObject, Serializer} from '../shared/serializer';
import {deserializeGenericEvent} from './event_deserializer';
@Injectable()
export class WebWorkerRootRenderer implements RootRenderer {
private _messageBroker: any /** TODO #9100 */;
public globalEvents: NamedEventEmitter = new NamedEventEmitter();
private _componentRenderers: Map<string, WebWorkerRenderer> =
new Map<string, WebWorkerRenderer>();
constructor(
messageBrokerFactory: ClientMessageBrokerFactory, bus: MessageBus,
private _serializer: Serializer, private _renderStore: RenderStore) {
this._messageBroker = messageBrokerFactory.createMessageBroker(RENDERER_CHANNEL);
bus.initChannel(EVENT_CHANNEL);
var source = bus.from(EVENT_CHANNEL);
source.subscribe({next: (message: any) => this._dispatchEvent(message)});
}
private _dispatchEvent(message: {[key: string]: any}): void {
var eventName = message['eventName'];
var target = message['eventTarget'];
var event = deserializeGenericEvent(message['event']);
if (isPresent(target)) {
this.globalEvents.dispatchEvent(eventNameWithTarget(target, eventName), event);
} else {
var element =
<WebWorkerRenderNode>this._serializer.deserialize(message['element'], RenderStoreObject);
element.events.dispatchEvent(eventName, event);
}
}
renderComponent(componentType: RenderComponentType): Renderer {
var result = this._componentRenderers.get(componentType.id);
if (isBlank(result)) {
result = new WebWorkerRenderer(this, componentType);
this._componentRenderers.set(componentType.id, result);
var id = this._renderStore.allocateId();
this._renderStore.store(result, id);
this.runOnService('renderComponent', [
new FnArg(componentType, RenderComponentType),
new FnArg(result, RenderStoreObject),
]);
}
return result;
}
runOnService(fnName: string, fnArgs: FnArg[]) {
var args = new UiArguments(fnName, fnArgs);
this._messageBroker.runOnService(args, null);
}
allocateNode(): WebWorkerRenderNode {
var result = new WebWorkerRenderNode();
var id = this._renderStore.allocateId();
this._renderStore.store(result, id);
return result;
}
allocateId(): number { return this._renderStore.allocateId(); }
destroyNodes(nodes: any[]) {
for (var i = 0; i < nodes.length; i++) {
this._renderStore.remove(nodes[i]);
}
}
}
export class WebWorkerRenderer implements Renderer, RenderStoreObject {
constructor(
private _rootRenderer: WebWorkerRootRenderer, private _componentType: RenderComponentType) {}
private _runOnService(fnName: string, fnArgs: FnArg[]) {
var fnArgsWithRenderer = [new FnArg(this, RenderStoreObject)].concat(fnArgs);
this._rootRenderer.runOnService(fnName, fnArgsWithRenderer);
}
selectRootElement(selectorOrNode: string, debugInfo?: RenderDebugInfo): any {
var node = this._rootRenderer.allocateNode();
this._runOnService(
'selectRootElement', [new FnArg(selectorOrNode, null), new FnArg(node, RenderStoreObject)]);
return node;
}
createElement(parentElement: any, name: string, debugInfo?: RenderDebugInfo): any {
var node = this._rootRenderer.allocateNode();
this._runOnService('createElement', [
new FnArg(parentElement, RenderStoreObject), new FnArg(name, null),
new FnArg(node, RenderStoreObject)
]);
return node;
}
createViewRoot(hostElement: any): any {
var viewRoot = this._componentType.encapsulation === ViewEncapsulation.Native ?
this._rootRenderer.allocateNode() :
hostElement;
this._runOnService(
'createViewRoot',
[new FnArg(hostElement, RenderStoreObject), new FnArg(viewRoot, RenderStoreObject)]);
return viewRoot;
}
createTemplateAnchor(parentElement: any, debugInfo?: RenderDebugInfo): any {
var node = this._rootRenderer.allocateNode();
this._runOnService(
'createTemplateAnchor',
[new FnArg(parentElement, RenderStoreObject), new FnArg(node, RenderStoreObject)]);
return node;
}
createText(parentElement: any, value: string, debugInfo?: RenderDebugInfo): any {
var node = this._rootRenderer.allocateNode();
this._runOnService('createText', [
new FnArg(parentElement, RenderStoreObject), new FnArg(value, null),
new FnArg(node, RenderStoreObject)
]);
return node;
}
projectNodes(parentElement: any, nodes: any[]) {
this._runOnService(
'projectNodes',
[new FnArg(parentElement, RenderStoreObject), new FnArg(nodes, RenderStoreObject)]);
}
attachViewAfter(node: any, viewRootNodes: any[]) {
this._runOnService(
'attachViewAfter',
[new FnArg(node, RenderStoreObject), new FnArg(viewRootNodes, RenderStoreObject)]);
}
detachView(viewRootNodes: any[]) {
this._runOnService('detachView', [new FnArg(viewRootNodes, RenderStoreObject)]);
}
destroyView(hostElement: any, viewAllNodes: any[]) {
this._runOnService(
'destroyView',
[new FnArg(hostElement, RenderStoreObject), new FnArg(viewAllNodes, RenderStoreObject)]);
this._rootRenderer.destroyNodes(viewAllNodes);
}
setElementProperty(renderElement: any, propertyName: string, propertyValue: any) {
this._runOnService('setElementProperty', [
new FnArg(renderElement, RenderStoreObject), new FnArg(propertyName, null),
new FnArg(propertyValue, null)
]);
}
setElementAttribute(renderElement: any, attributeName: string, attributeValue: string) {
this._runOnService('setElementAttribute', [
new FnArg(renderElement, RenderStoreObject), new FnArg(attributeName, null),
new FnArg(attributeValue, null)
]);
}
setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string) {
this._runOnService('setBindingDebugInfo', [
new FnArg(renderElement, RenderStoreObject), new FnArg(propertyName, null),
new FnArg(propertyValue, null)
]);
}
setElementClass(renderElement: any, className: string, isAdd: boolean) {
this._runOnService('setElementClass', [
new FnArg(renderElement, RenderStoreObject), new FnArg(className, null),
new FnArg(isAdd, null)
]);
}
setElementStyle(renderElement: any, styleName: string, styleValue: string) {
this._runOnService('setElementStyle', [
new FnArg(renderElement, RenderStoreObject), new FnArg(styleName, null),
new FnArg(styleValue, null)
]);
}
invokeElementMethod(renderElement: any, methodName: string, args?: any[]) {
this._runOnService('invokeElementMethod', [
new FnArg(renderElement, RenderStoreObject), new FnArg(methodName, null),
new FnArg(args, null)
]);
}
setText(renderNode: any, text: string) {
this._runOnService(
'setText', [new FnArg(renderNode, RenderStoreObject), new FnArg(text, null)]);
}
listen(renderElement: WebWorkerRenderNode, name: string, callback: Function): Function {
renderElement.events.listen(name, callback);
var unlistenCallbackId = this._rootRenderer.allocateId();
this._runOnService('listen', [
new FnArg(renderElement, RenderStoreObject), new FnArg(name, null),
new FnArg(unlistenCallbackId, null)
]);
return () => {
renderElement.events.unlisten(name, callback);
this._runOnService('listenDone', [new FnArg(unlistenCallbackId, null)]);
};
}
listenGlobal(target: string, name: string, callback: Function): Function {
this._rootRenderer.globalEvents.listen(eventNameWithTarget(target, name), callback);
var unlistenCallbackId = this._rootRenderer.allocateId();
this._runOnService(
'listenGlobal',
[new FnArg(target, null), new FnArg(name, null), new FnArg(unlistenCallbackId, null)]);
return () => {
this._rootRenderer.globalEvents.unlisten(eventNameWithTarget(target, name), callback);
this._runOnService('listenDone', [new FnArg(unlistenCallbackId, null)]);
};
}
animate(
element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[],
duration: number, delay: number, easing: string): AnimationPlayer {
// TODO
return null;
}
}
export class NamedEventEmitter {
private _listeners: Map<string, Function[]>;
private _getListeners(eventName: string): Function[] {
if (isBlank(this._listeners)) {
this._listeners = new Map<string, Function[]>();
}
var listeners = this._listeners.get(eventName);
if (isBlank(listeners)) {
listeners = [];
this._listeners.set(eventName, listeners);
}
return listeners;
}
listen(eventName: string, callback: Function) { this._getListeners(eventName).push(callback); }
unlisten(eventName: string, callback: Function) {
ListWrapper.remove(this._getListeners(eventName), callback);
}
dispatchEvent(eventName: string, event: any) {
var listeners = this._getListeners(eventName);
for (var i = 0; i < listeners.length; i++) {
listeners[i](event);
}
}
}
function eventNameWithTarget(target: string, eventName: string): string {
return `${target}:${eventName}`;
}
export class WebWorkerRenderNode { events: NamedEventEmitter = new NamedEventEmitter(); }

View File

@ -1,210 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Type} from '@angular/core';
import {DomAdapter, setRootDomAdapter} from '../../dom/dom_adapter';
/**
* This adapter is required to log error messages.
*
* Note: other methods all throw as the DOM is not accessible directly in web worker context.
*/
export class WorkerDomAdapter extends DomAdapter {
static makeCurrent() { setRootDomAdapter(new WorkerDomAdapter()); }
logError(error: any /** TODO #9100 */) {
if (console.error) {
console.error(error);
} else {
console.log(error);
}
}
log(error: any /** TODO #9100 */) { console.log(error); }
logGroup(error: any /** TODO #9100 */) {
if (console.group) {
console.group(error);
this.logError(error);
} else {
console.log(error);
}
}
logGroupEnd() {
if (console.groupEnd) {
console.groupEnd();
}
}
hasProperty(element: any /** TODO #9100 */, name: string): boolean { throw 'not implemented'; }
setProperty(el: Element, name: string, value: any) { throw 'not implemented'; }
getProperty(el: Element, name: string): any { throw 'not implemented'; }
invoke(el: Element, methodName: string, args: any[]): any { throw 'not implemented'; }
get attrToPropMap(): {[key: string]: string} { throw 'not implemented'; }
set attrToPropMap(value: {[key: string]: string}) { throw 'not implemented'; }
parse(templateHtml: string) { throw 'not implemented'; }
query(selector: string): any { throw 'not implemented'; }
querySelector(el: any /** TODO #9100 */, selector: string): HTMLElement {
throw 'not implemented';
}
querySelectorAll(el: any /** TODO #9100 */, selector: string): any[] { throw 'not implemented'; }
on(el: any /** TODO #9100 */, evt: any /** TODO #9100 */, listener: any /** TODO #9100 */) {
throw 'not implemented';
}
onAndCancel(
el: any /** TODO #9100 */, evt: any /** TODO #9100 */,
listener: any /** TODO #9100 */): Function {
throw 'not implemented';
}
dispatchEvent(el: any /** TODO #9100 */, evt: any /** TODO #9100 */) { throw 'not implemented'; }
createMouseEvent(eventType: any /** TODO #9100 */): any { throw 'not implemented'; }
createEvent(eventType: string): any { throw 'not implemented'; }
preventDefault(evt: any /** TODO #9100 */) { throw 'not implemented'; }
isPrevented(evt: any /** TODO #9100 */): boolean { throw 'not implemented'; }
getInnerHTML(el: any /** TODO #9100 */): string { throw 'not implemented'; }
getTemplateContent(el: any /** TODO #9100 */): any { throw 'not implemented'; }
getOuterHTML(el: any /** TODO #9100 */): string { throw 'not implemented'; }
nodeName(node: any /** TODO #9100 */): string { throw 'not implemented'; }
nodeValue(node: any /** TODO #9100 */): string { throw 'not implemented'; }
type(node: any /** TODO #9100 */): string { throw 'not implemented'; }
content(node: any /** TODO #9100 */): any { throw 'not implemented'; }
firstChild(el: any /** TODO #9100 */): Node { throw 'not implemented'; }
nextSibling(el: any /** TODO #9100 */): Node { throw 'not implemented'; }
parentElement(el: any /** TODO #9100 */): Node { throw 'not implemented'; }
childNodes(el: any /** TODO #9100 */): Node[] { throw 'not implemented'; }
childNodesAsList(el: any /** TODO #9100 */): Node[] { throw 'not implemented'; }
clearNodes(el: any /** TODO #9100 */) { throw 'not implemented'; }
appendChild(el: any /** TODO #9100 */, node: any /** TODO #9100 */) { throw 'not implemented'; }
removeChild(el: any /** TODO #9100 */, node: any /** TODO #9100 */) { throw 'not implemented'; }
replaceChild(
el: any /** TODO #9100 */, newNode: any /** TODO #9100 */, oldNode: any /** TODO #9100 */) {
throw 'not implemented';
}
remove(el: any /** TODO #9100 */): Node { throw 'not implemented'; }
insertBefore(el: any /** TODO #9100 */, node: any /** TODO #9100 */) { throw 'not implemented'; }
insertAllBefore(el: any /** TODO #9100 */, nodes: any /** TODO #9100 */) {
throw 'not implemented';
}
insertAfter(el: any /** TODO #9100 */, node: any /** TODO #9100 */) { throw 'not implemented'; }
setInnerHTML(el: any /** TODO #9100 */, value: any /** TODO #9100 */) { throw 'not implemented'; }
getText(el: any /** TODO #9100 */): string { throw 'not implemented'; }
setText(el: any /** TODO #9100 */, value: string) { throw 'not implemented'; }
getValue(el: any /** TODO #9100 */): string { throw 'not implemented'; }
setValue(el: any /** TODO #9100 */, value: string) { throw 'not implemented'; }
getChecked(el: any /** TODO #9100 */): boolean { throw 'not implemented'; }
setChecked(el: any /** TODO #9100 */, value: boolean) { throw 'not implemented'; }
createComment(text: string): any { throw 'not implemented'; }
createTemplate(html: any /** TODO #9100 */): HTMLElement { throw 'not implemented'; }
createElement(tagName: any /** TODO #9100 */, doc?: any /** TODO #9100 */): HTMLElement {
throw 'not implemented';
}
createElementNS(ns: string, tagName: string, doc?: any /** TODO #9100 */): Element {
throw 'not implemented';
}
createTextNode(text: string, doc?: any /** TODO #9100 */): Text { throw 'not implemented'; }
createScriptTag(attrName: string, attrValue: string, doc?: any /** TODO #9100 */): HTMLElement {
throw 'not implemented';
}
createStyleElement(css: string, doc?: any /** TODO #9100 */): HTMLStyleElement {
throw 'not implemented';
}
createShadowRoot(el: any /** TODO #9100 */): any { throw 'not implemented'; }
getShadowRoot(el: any /** TODO #9100 */): any { throw 'not implemented'; }
getHost(el: any /** TODO #9100 */): any { throw 'not implemented'; }
getDistributedNodes(el: any /** TODO #9100 */): Node[] { throw 'not implemented'; }
clone(node: Node): Node { throw 'not implemented'; }
getElementsByClassName(element: any /** TODO #9100 */, name: string): HTMLElement[] {
throw 'not implemented';
}
getElementsByTagName(element: any /** TODO #9100 */, name: string): HTMLElement[] {
throw 'not implemented';
}
classList(element: any /** TODO #9100 */): any[] { throw 'not implemented'; }
addClass(element: any /** TODO #9100 */, className: string) { throw 'not implemented'; }
removeClass(element: any /** TODO #9100 */, className: string) { throw 'not implemented'; }
hasClass(element: any /** TODO #9100 */, className: string): boolean { throw 'not implemented'; }
setStyle(element: any /** TODO #9100 */, styleName: string, styleValue: string) {
throw 'not implemented';
}
removeStyle(element: any /** TODO #9100 */, styleName: string) { throw 'not implemented'; }
getStyle(element: any /** TODO #9100 */, styleName: string): string { throw 'not implemented'; }
hasStyle(element: any /** TODO #9100 */, styleName: string, styleValue?: string): boolean {
throw 'not implemented';
}
tagName(element: any /** TODO #9100 */): string { throw 'not implemented'; }
attributeMap(element: any /** TODO #9100 */): Map<string, string> { throw 'not implemented'; }
hasAttribute(element: any /** TODO #9100 */, attribute: string): boolean {
throw 'not implemented';
}
hasAttributeNS(element: any /** TODO #9100 */, ns: string, attribute: string): boolean {
throw 'not implemented';
}
getAttribute(element: any /** TODO #9100 */, attribute: string): string {
throw 'not implemented';
}
getAttributeNS(element: any /** TODO #9100 */, ns: string, attribute: string): string {
throw 'not implemented';
}
setAttribute(element: any /** TODO #9100 */, name: string, value: string) {
throw 'not implemented';
}
setAttributeNS(element: any /** TODO #9100 */, ns: string, name: string, value: string) {
throw 'not implemented';
}
removeAttribute(element: any /** TODO #9100 */, attribute: string) { throw 'not implemented'; }
removeAttributeNS(element: any /** TODO #9100 */, ns: string, attribute: string) {
throw 'not implemented';
}
templateAwareRoot(el: any /** TODO #9100 */) { throw 'not implemented'; }
createHtmlDocument(): HTMLDocument { throw 'not implemented'; }
defaultDoc(): HTMLDocument { throw 'not implemented'; }
getBoundingClientRect(el: any /** TODO #9100 */) { throw 'not implemented'; }
getTitle(): string { throw 'not implemented'; }
setTitle(newTitle: string) { throw 'not implemented'; }
elementMatches(n: any /** TODO #9100 */, selector: string): boolean { throw 'not implemented'; }
isTemplateElement(el: any): boolean { throw 'not implemented'; }
isTextNode(node: any /** TODO #9100 */): boolean { throw 'not implemented'; }
isCommentNode(node: any /** TODO #9100 */): boolean { throw 'not implemented'; }
isElementNode(node: any /** TODO #9100 */): boolean { throw 'not implemented'; }
hasShadowRoot(node: any /** TODO #9100 */): boolean { throw 'not implemented'; }
isShadowRoot(node: any /** TODO #9100 */): boolean { throw 'not implemented'; }
importIntoDoc(node: Node): Node { throw 'not implemented'; }
adoptNode(node: Node): Node { throw 'not implemented'; }
getHref(element: any /** TODO #9100 */): string { throw 'not implemented'; }
getEventKey(event: any /** TODO #9100 */): string { throw 'not implemented'; }
resolveAndSetHref(element: any /** TODO #9100 */, baseUrl: string, href: string) {
throw 'not implemented';
}
supportsDOMEvents(): boolean { throw 'not implemented'; }
supportsNativeShadowDOM(): boolean { throw 'not implemented'; }
getGlobalEventTarget(target: string): any { throw 'not implemented'; }
getHistory(): History { throw 'not implemented'; }
getLocation(): Location { throw 'not implemented'; }
getBaseHref(): string { throw 'not implemented'; }
resetBaseElement(): void { throw 'not implemented'; }
getUserAgent(): string { throw 'not implemented'; }
setData(element: any /** TODO #9100 */, name: string, value: string) { throw 'not implemented'; }
getComputedStyle(element: any /** TODO #9100 */): any { throw 'not implemented'; }
getData(element: any /** TODO #9100 */, name: string): string { throw 'not implemented'; }
setGlobalVar(name: string, value: any) { throw 'not implemented'; }
performanceNow(): number { throw 'not implemented'; }
getAnimationPrefix(): string { throw 'not implemented'; }
getTransitionEnd(): string { throw 'not implemented'; }
supportsAnimation(): boolean { throw 'not implemented'; }
supportsWebAnimation(): boolean { throw 'not implemented'; }
supportsCookies(): boolean { return false; }
getCookie(name: string): string { throw 'not implemented'; }
setCookie(name: string, value: string) { throw 'not implemented'; }
}

View File

@ -1,88 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {CommonModule} from '@angular/common';
import {APP_INITIALIZER, ApplicationModule, ClassProvider, ErrorHandler, ExistingProvider, FactoryProvider, NgModule, NgZone, PlatformRef, Provider, RootRenderer, TypeProvider, ValueProvider, createPlatformFactory, platformCore} from '@angular/core';
import {BROWSER_SANITIZATION_PROVIDERS} from './browser';
import {print} from './facade/lang';
import {ON_WEB_WORKER} from './web_workers/shared/api';
import {ClientMessageBrokerFactory, ClientMessageBrokerFactory_} from './web_workers/shared/client_message_broker';
import {MessageBus} from './web_workers/shared/message_bus';
import {PostMessageBus, PostMessageBusSink, PostMessageBusSource} from './web_workers/shared/post_message_bus';
import {RenderStore} from './web_workers/shared/render_store';
import {Serializer} from './web_workers/shared/serializer';
import {ServiceMessageBrokerFactory, ServiceMessageBrokerFactory_} from './web_workers/shared/service_message_broker';
import {WebWorkerRootRenderer} from './web_workers/worker/renderer';
import {WorkerDomAdapter} from './web_workers/worker/worker_adapter';
/**
* @experimental
*/
export const platformWorkerApp = createPlatformFactory(platformCore, 'workerApp');
/**
* Exception handler factory function.
*
* @experimental
*/
export function errorHandler(): ErrorHandler {
return new ErrorHandler();
}
// TODO(jteplitz602) remove this and compile with lib.webworker.d.ts (#3492)
let _postMessage = {
postMessage: (message: any, transferrables?: [ArrayBuffer]) => {
(<any>postMessage)(message, transferrables);
}
};
/**
* MessageBus factory function.
*
* @experimental
*/
export function createMessageBus(zone: NgZone): MessageBus {
let sink = new PostMessageBusSink(_postMessage);
let source = new PostMessageBusSource();
let bus = new PostMessageBus(sink, source);
bus.attachToZone(zone);
return bus;
}
/**
* Application initializer for web workers.
*
* @experimental
*/
export function setupWebWorker(): void {
WorkerDomAdapter.makeCurrent();
}
/**
* The ng module for the worker app side.
*
* @experimental
*/
@NgModule({
providers: [
BROWSER_SANITIZATION_PROVIDERS, Serializer,
{provide: ClientMessageBrokerFactory, useClass: ClientMessageBrokerFactory_},
{provide: ServiceMessageBrokerFactory, useClass: ServiceMessageBrokerFactory_},
WebWorkerRootRenderer, {provide: RootRenderer, useExisting: WebWorkerRootRenderer},
{provide: ON_WEB_WORKER, useValue: true}, RenderStore,
{provide: ErrorHandler, useFactory: errorHandler, deps: []},
{provide: MessageBus, useFactory: createMessageBus, deps: [NgZone]},
{provide: APP_INITIALIZER, useValue: setupWebWorker, multi: true}
],
exports: [CommonModule, ApplicationModule]
})
export class WorkerAppModule {
}

View File

@ -1,172 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {ClassProvider, ErrorHandler, ExistingProvider, FactoryProvider, Injectable, Injector, NgZone, OpaqueToken, PLATFORM_INITIALIZER, PlatformRef, Provider, RootRenderer, Testability, TypeProvider, ValueProvider, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
import {BROWSER_SANITIZATION_PROVIDERS} from './browser';
import {BrowserDomAdapter} from './browser/browser_adapter';
import {BrowserGetTestability} from './browser/testability';
import {AnimationDriver} from './dom/animation_driver';
import {getDOM} from './dom/dom_adapter';
import {DomRootRenderer, DomRootRenderer_} from './dom/dom_renderer';
import {DOCUMENT} from './dom/dom_tokens';
import {DomEventsPlugin} from './dom/events/dom_events';
import {EVENT_MANAGER_PLUGINS, EventManager} from './dom/events/event_manager';
import {HAMMER_GESTURE_CONFIG, HammerGestureConfig, HammerGesturesPlugin} from './dom/events/hammer_gestures';
import {KeyEventsPlugin} from './dom/events/key_events';
import {DomSharedStylesHost, SharedStylesHost} from './dom/shared_styles_host';
import {ON_WEB_WORKER} from './web_workers/shared/api';
import {ClientMessageBrokerFactory, ClientMessageBrokerFactory_} from './web_workers/shared/client_message_broker';
import {MessageBus} from './web_workers/shared/message_bus';
import {PostMessageBus, PostMessageBusSink, PostMessageBusSource} from './web_workers/shared/post_message_bus';
import {RenderStore} from './web_workers/shared/render_store';
import {Serializer} from './web_workers/shared/serializer';
import {ServiceMessageBrokerFactory, ServiceMessageBrokerFactory_} from './web_workers/shared/service_message_broker';
import {MessageBasedRenderer} from './web_workers/ui/renderer';
/**
* Wrapper class that exposes the Worker
* and underlying {@link MessageBus} for lower level message passing.
*
* @experimental WebWorker support is currently experimental.
*/
@Injectable()
export class WebWorkerInstance {
public worker: Worker;
public bus: MessageBus;
/** @internal */
public init(worker: Worker, bus: MessageBus) {
this.worker = worker;
this.bus = bus;
}
}
/**
* @experimental WebWorker support is currently experimental.
*/
export const WORKER_SCRIPT: OpaqueToken = new OpaqueToken('WebWorkerScript');
/**
* A multiple providers used to automatically call the `start()` method after the service is
* created.
*
* TODO(vicb): create an interface for startable services to implement
* @experimental WebWorker support is currently experimental.
*/
export const WORKER_UI_STARTABLE_MESSAGING_SERVICE =
new OpaqueToken('WorkerRenderStartableMsgService');
/**
* @experimental WebWorker support is currently experimental.
*/
export const _WORKER_UI_PLATFORM_PROVIDERS: Provider[] = [
{provide: NgZone, useFactory: createNgZone, deps: []},
MessageBasedRenderer,
{provide: WORKER_UI_STARTABLE_MESSAGING_SERVICE, useExisting: MessageBasedRenderer, multi: true},
BROWSER_SANITIZATION_PROVIDERS,
{provide: ErrorHandler, useFactory: _exceptionHandler, deps: []},
{provide: DOCUMENT, useFactory: _document, deps: []},
// TODO(jteplitz602): Investigate if we definitely need EVENT_MANAGER on the render thread
// #5298
{provide: EVENT_MANAGER_PLUGINS, useClass: DomEventsPlugin, multi: true},
{provide: EVENT_MANAGER_PLUGINS, useClass: KeyEventsPlugin, multi: true},
{provide: EVENT_MANAGER_PLUGINS, useClass: HammerGesturesPlugin, multi: true},
{provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig},
{provide: DomRootRenderer, useClass: DomRootRenderer_},
{provide: RootRenderer, useExisting: DomRootRenderer},
{provide: SharedStylesHost, useExisting: DomSharedStylesHost},
{provide: ServiceMessageBrokerFactory, useClass: ServiceMessageBrokerFactory_},
{provide: ClientMessageBrokerFactory, useClass: ClientMessageBrokerFactory_},
{provide: AnimationDriver, useFactory: _resolveDefaultAnimationDriver, deps: []},
Serializer,
{provide: ON_WEB_WORKER, useValue: false},
RenderStore,
DomSharedStylesHost,
Testability,
EventManager,
WebWorkerInstance,
{
provide: PLATFORM_INITIALIZER,
useFactory: initWebWorkerRenderPlatform,
multi: true,
deps: [Injector]
},
{provide: MessageBus, useFactory: messageBusFactory, deps: [WebWorkerInstance]}
];
function initializeGenericWorkerRenderer(injector: Injector) {
var bus = injector.get(MessageBus);
let zone = injector.get(NgZone);
bus.attachToZone(zone);
// initialize message services after the bus has been created
let services = injector.get(WORKER_UI_STARTABLE_MESSAGING_SERVICE);
zone.runGuarded(() => { services.forEach((svc: any) => { svc.start(); }); });
}
function messageBusFactory(instance: WebWorkerInstance): MessageBus {
return instance.bus;
}
function initWebWorkerRenderPlatform(injector: Injector): () => void {
return () => {
BrowserDomAdapter.makeCurrent();
BrowserGetTestability.init();
var scriptUri: string;
try {
scriptUri = injector.get(WORKER_SCRIPT);
} catch (e) {
throw new Error(
'You must provide your WebWorker\'s initialization script with the WORKER_SCRIPT token');
}
let instance = injector.get(WebWorkerInstance);
spawnWebWorker(scriptUri, instance);
initializeGenericWorkerRenderer(injector);
};
}
/**
* @experimental WebWorker support is currently experimental.
*/
export const platformWorkerUi =
createPlatformFactory(platformCore, 'workerUi', _WORKER_UI_PLATFORM_PROVIDERS);
function _exceptionHandler(): ErrorHandler {
return new ErrorHandler();
}
function _document(): any {
return getDOM().defaultDoc();
}
function createNgZone(): NgZone {
return new NgZone({enableLongStackTrace: isDevMode()});
}
/**
* Spawns a new class and initializes the WebWorkerInstance
*/
function spawnWebWorker(uri: string, instance: WebWorkerInstance): void {
var webWorker: Worker = new Worker(uri);
var sink = new PostMessageBusSink(webWorker);
var source = new PostMessageBusSource(webWorker);
var bus = new PostMessageBus(sink, source);
instance.init(webWorker, bus);
}
function _resolveDefaultAnimationDriver(): AnimationDriver {
// web workers have not been tested or configured to
// work with animations just yet...
return AnimationDriver.NOOP;
}