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:

committed by
Victor Berchet

parent
0f68351979
commit
71ae2c4525
@ -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(); }
|
||||
|
@ -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';
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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');
|
@ -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[]) {}
|
||||
}
|
@ -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>;
|
||||
}
|
@ -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';
|
@ -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) {}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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) {}
|
||||
}
|
@ -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 {}
|
@ -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'];
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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());
|
||||
};
|
||||
}
|
@ -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; }
|
||||
}
|
@ -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(); }
|
||||
}
|
@ -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;
|
||||
}
|
@ -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()); };
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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(); }
|
@ -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'; }
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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;
|
||||
}
|
Reference in New Issue
Block a user