refactor: move angular source to /packages rather than modules/@angular
This commit is contained in:
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @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 '@angular/core';
|
||||
import {Serializer, SerializerTypes} from '../shared/serializer';
|
||||
|
||||
import {serializeEventWithTarget, serializeGenericEvent, serializeKeyboardEvent, serializeMouseEvent, serializeTransitionEvent} from './event_serializer';
|
||||
|
||||
export class EventDispatcher {
|
||||
constructor(private _sink: EventEmitter<any>, private _serializer: Serializer) {}
|
||||
|
||||
dispatchAnimationEvent(player: any, phaseName: string, element: any): boolean {
|
||||
this._sink.emit({
|
||||
'element': this._serializer.serialize(element, SerializerTypes.RENDER_STORE_OBJECT),
|
||||
'animationPlayer': this._serializer.serialize(player, SerializerTypes.RENDER_STORE_OBJECT),
|
||||
'phaseName': phaseName,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
dispatchRenderEvent(element: any, eventTarget: string, eventName: string, event: any): boolean {
|
||||
let serializedEvent: any;
|
||||
// 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, SerializerTypes.RENDER_STORE_OBJECT),
|
||||
'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;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
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} {
|
||||
const 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} {
|
||||
const serializedEvent = serializeEvent(e, KEYBOARD_EVENT_PROPERTIES);
|
||||
return addTarget(e, serializedEvent);
|
||||
}
|
||||
|
||||
export function serializeTransitionEvent(e: TransitionEvent): {[key: string]: any} {
|
||||
const 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())) {
|
||||
const target = <HTMLInputElement>e.target;
|
||||
serializedEvent['target'] = {'value': target.value};
|
||||
if (target.files) {
|
||||
serializedEvent['target']['files'] = target.files;
|
||||
}
|
||||
}
|
||||
return serializedEvent;
|
||||
}
|
||||
|
||||
function serializeEvent(e: any, properties: string[]): {[key: string]: any} {
|
||||
const serialized: {[k: string]: any} = {};
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
const prop = properties[i];
|
||||
serialized[prop] = e[prop];
|
||||
}
|
||||
return serialized;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @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, Provider} from '@angular/core';
|
||||
|
||||
import {ɵBrowserPlatformLocation as BrowserPlatformLocation} from '@angular/platform-browser';
|
||||
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: Provider[] = [
|
||||
MessageBasedPlatformLocation, BrowserPlatformLocation,
|
||||
{provide: PLATFORM_INITIALIZER, useFactory: initUiLocation, multi: true, deps: [Injector]}
|
||||
];
|
||||
|
||||
function initUiLocation(injector: Injector): () => void {
|
||||
return () => {
|
||||
const zone = injector.get(NgZone);
|
||||
|
||||
zone.runGuarded(() => injector.get(MessageBasedPlatformLocation).start());
|
||||
};
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @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 {EventEmitter, Injectable} from '@angular/core';
|
||||
import {ɵBrowserPlatformLocation as BrowserPlatformLocation} from '@angular/platform-browser';
|
||||
import {MessageBus} from '../shared/message_bus';
|
||||
import {ROUTER_CHANNEL} from '../shared/messaging_api';
|
||||
import {LocationType, Serializer, SerializerTypes} 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>this._sendUrlChangeEvent.bind(this));
|
||||
this._platformLocation.onHashChange(
|
||||
<LocationChangeListener>this._sendUrlChangeEvent.bind(this));
|
||||
this._broker = this._brokerFactory.createMessageBroker(ROUTER_CHANNEL);
|
||||
this._channelSink = bus.to(ROUTER_CHANNEL);
|
||||
}
|
||||
|
||||
start(): void {
|
||||
const P = SerializerTypes.PRIMITIVE;
|
||||
|
||||
this._broker.registerMethod('getLocation', null, this._getLocation.bind(this), LocationType);
|
||||
this._broker.registerMethod('setPathname', [P], this._setPathname.bind(this));
|
||||
this._broker.registerMethod(
|
||||
'pushState', [P, P, P], this._platformLocation.pushState.bind(this._platformLocation));
|
||||
this._broker.registerMethod(
|
||||
'replaceState', [P, P, P],
|
||||
this._platformLocation.replaceState.bind(this._platformLocation));
|
||||
this._broker.registerMethod(
|
||||
'forward', null, this._platformLocation.forward.bind(this._platformLocation));
|
||||
this._broker.registerMethod(
|
||||
'back', null, this._platformLocation.back.bind(this._platformLocation));
|
||||
}
|
||||
|
||||
private _getLocation(): Promise<Location> {
|
||||
return Promise.resolve(this._platformLocation.location);
|
||||
}
|
||||
|
||||
private _sendUrlChangeEvent(e: Event): void {
|
||||
this._channelSink.emit({
|
||||
'event': {'type': e.type},
|
||||
'location': this._serializer.serialize(this._platformLocation.location, LocationType),
|
||||
});
|
||||
}
|
||||
|
||||
private _setPathname(pathname: string): void { this._platformLocation.pathname = pathname; }
|
||||
}
|
147
packages/platform-webworker/src/web_workers/ui/renderer.ts
Normal file
147
packages/platform-webworker/src/web_workers/ui/renderer.ts
Normal file
@ -0,0 +1,147 @@
|
||||
/**
|
||||
* @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, Renderer2, RendererFactory2, RendererType2, RootRenderer} from '@angular/core';
|
||||
|
||||
import {MessageBus} from '../shared/message_bus';
|
||||
import {EVENT_2_CHANNEL, RENDERER_2_CHANNEL} from '../shared/messaging_api';
|
||||
import {RenderStore} from '../shared/render_store';
|
||||
import {Serializer, SerializerTypes} from '../shared/serializer';
|
||||
import {ServiceMessageBroker, ServiceMessageBrokerFactory} from '../shared/service_message_broker';
|
||||
import {EventDispatcher} from '../ui/event_dispatcher';
|
||||
|
||||
@Injectable()
|
||||
export class MessageBasedRenderer2 {
|
||||
private _eventDispatcher: EventDispatcher;
|
||||
|
||||
constructor(
|
||||
private _brokerFactory: ServiceMessageBrokerFactory, private _bus: MessageBus,
|
||||
private _serializer: Serializer, private _renderStore: RenderStore,
|
||||
private _rendererFactory: RendererFactory2) {}
|
||||
|
||||
start(): void {
|
||||
const broker = this._brokerFactory.createMessageBroker(RENDERER_2_CHANNEL);
|
||||
|
||||
this._bus.initChannel(EVENT_2_CHANNEL);
|
||||
this._eventDispatcher = new EventDispatcher(this._bus.to(EVENT_2_CHANNEL), this._serializer);
|
||||
|
||||
const [RSO, P, CRT] = [
|
||||
SerializerTypes.RENDER_STORE_OBJECT,
|
||||
SerializerTypes.PRIMITIVE,
|
||||
SerializerTypes.RENDERER_TYPE_2,
|
||||
];
|
||||
|
||||
const methods: any[][] = [
|
||||
['createRenderer', this.createRenderer, RSO, CRT, P],
|
||||
['createElement', this.createElement, RSO, P, P, P],
|
||||
['createComment', this.createComment, RSO, P, P], ['createText', this.createText, RSO, P, P],
|
||||
['appendChild', this.appendChild, RSO, RSO, RSO],
|
||||
['insertBefore', this.insertBefore, RSO, RSO, RSO, RSO],
|
||||
['removeChild', this.removeChild, RSO, RSO, RSO],
|
||||
['selectRootElement', this.selectRootElement, RSO, P, P],
|
||||
['parentNode', this.parentNode, RSO, RSO, P], ['nextSibling', this.nextSibling, RSO, RSO, P],
|
||||
['setAttribute', this.setAttribute, RSO, RSO, P, P, P],
|
||||
['removeAttribute', this.removeAttribute, RSO, RSO, P, P],
|
||||
['addClass', this.addClass, RSO, RSO, P], ['removeClass', this.removeClass, RSO, RSO, P],
|
||||
['setStyle', this.setStyle, RSO, RSO, P, P, P, P],
|
||||
['removeStyle', this.removeStyle, RSO, RSO, P, P],
|
||||
['setProperty', this.setProperty, RSO, RSO, P, P], ['setValue', this.setValue, RSO, RSO, P],
|
||||
['listen', this.listen, RSO, RSO, P, P, P], ['unlisten', this.unlisten, RSO, RSO],
|
||||
['destroy', this.destroy, RSO], ['destroyNode', this.destroyNode, RSO, P]
|
||||
|
||||
];
|
||||
|
||||
methods.forEach(([name, method, ...argTypes]: any[]) => {
|
||||
broker.registerMethod(name, argTypes, method.bind(this));
|
||||
});
|
||||
}
|
||||
|
||||
private destroy(r: Renderer2) { r.destroy(); }
|
||||
|
||||
private destroyNode(r: Renderer2, node: any) {
|
||||
if (r.destroyNode) {
|
||||
r.destroyNode(node);
|
||||
}
|
||||
this._renderStore.remove(node);
|
||||
}
|
||||
|
||||
private createRenderer(el: any, type: RendererType2, id: number) {
|
||||
this._renderStore.store(this._rendererFactory.createRenderer(el, type), id);
|
||||
}
|
||||
|
||||
private createElement(r: Renderer2, name: string, namespace: string, id: number) {
|
||||
this._renderStore.store(r.createElement(name, namespace), id);
|
||||
}
|
||||
|
||||
private createComment(r: Renderer2, value: string, id: number) {
|
||||
this._renderStore.store(r.createComment(value), id);
|
||||
}
|
||||
|
||||
private createText(r: Renderer2, value: string, id: number) {
|
||||
this._renderStore.store(r.createText(value), id);
|
||||
}
|
||||
|
||||
private appendChild(r: Renderer2, parent: any, child: any) { r.appendChild(parent, child); }
|
||||
|
||||
private insertBefore(r: Renderer2, parent: any, child: any, ref: any) {
|
||||
r.insertBefore(parent, child, ref);
|
||||
}
|
||||
|
||||
private removeChild(r: Renderer2, parent: any, child: any) { r.removeChild(parent, child); }
|
||||
|
||||
private selectRootElement(r: Renderer2, selector: string, id: number) {
|
||||
this._renderStore.store(r.selectRootElement(selector), id);
|
||||
}
|
||||
|
||||
private parentNode(r: Renderer2, node: any, id: number) {
|
||||
this._renderStore.store(r.parentNode(node), id);
|
||||
}
|
||||
|
||||
private nextSibling(r: Renderer2, node: any, id: number) {
|
||||
this._renderStore.store(r.nextSibling(node), id);
|
||||
}
|
||||
|
||||
private setAttribute(r: Renderer2, el: any, name: string, value: string, namespace: string) {
|
||||
r.setAttribute(el, name, value, namespace);
|
||||
}
|
||||
|
||||
private removeAttribute(r: Renderer2, el: any, name: string, namespace: string) {
|
||||
r.removeAttribute(el, name, namespace);
|
||||
}
|
||||
|
||||
private addClass(r: Renderer2, el: any, name: string) { r.addClass(el, name); }
|
||||
|
||||
private removeClass(r: Renderer2, el: any, name: string) { r.removeClass(el, name); }
|
||||
|
||||
private setStyle(
|
||||
r: Renderer2, el: any, style: string, value: any, hasVendorPrefix: boolean,
|
||||
hasImportant: boolean) {
|
||||
r.setStyle(el, style, value, hasVendorPrefix, hasImportant);
|
||||
}
|
||||
|
||||
private removeStyle(r: Renderer2, el: any, style: string, hasVendorPrefix: boolean) {
|
||||
r.removeStyle(el, style, hasVendorPrefix);
|
||||
}
|
||||
|
||||
private setProperty(r: Renderer2, el: any, name: string, value: any) {
|
||||
r.setProperty(el, name, value);
|
||||
}
|
||||
|
||||
private setValue(r: Renderer2, node: any, value: string) { r.setValue(node, value); }
|
||||
|
||||
private listen(r: Renderer2, el: any, elName: string, eventName: string, unlistenId: number) {
|
||||
const listener = (event: any) => {
|
||||
return this._eventDispatcher.dispatchRenderEvent(el, elName, eventName, event);
|
||||
};
|
||||
|
||||
const unlisten = r.listen(el || elName, eventName, listener);
|
||||
this._renderStore.store(unlisten, unlistenId);
|
||||
}
|
||||
|
||||
private unlisten(r: Renderer2, unlisten: () => boolean) { unlisten(); }
|
||||
}
|
Reference in New Issue
Block a user