Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Remove Evented and Destroyable from WidgetBase #761

Merged
merged 2 commits into from
Nov 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/NodeHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class NodeHandler extends Evented implements NodeHandlerInterface {
this.emit({ type: key });
}

public addRoot(element: HTMLElement, key?: string): void {
public addRoot(): void {
this.emit({ type: NodeEventType.Widget });
}

Expand Down
60 changes: 19 additions & 41 deletions src/WidgetBase.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { EventTypedObject } from '@dojo/interfaces/core';
import { Evented } from '@dojo/core/Evented';
import Map from '@dojo/shim/Map';
import WeakMap from '@dojo/shim/WeakMap';
import { v } from './d';
Expand Down Expand Up @@ -53,7 +52,7 @@ const boundAuto = auto.bind(null);
/**
* Main widget base for all widgets to extend
*/
export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends Evented implements WidgetBaseInterface<P, C> {
export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> implements WidgetBaseInterface<P, C> {

/**
* static identifier
Expand Down Expand Up @@ -87,11 +86,6 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E

private _cachedDNode: DNode | DNode[];

/**
* map of specific property diff functions
*/
private _diffPropertyFunctionMap: Map<string, string>;

/**
* map of decorators that are applied to this widget
*/
Expand All @@ -112,54 +106,39 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E

private _boundInvalidate: () => void;

private _nodeHandler: NodeHandler;
public readonly nodeHandler: NodeHandler = new NodeHandler();

protected parentInvalidate: Function;

/**
* @constructor
*/
constructor() {
super({});
constructor(invalidate?: Function) {
if (invalidate) {
this.parentInvalidate = invalidate;
}

this._children = [];
this._decoratorCache = new Map<string, any[]>();
this._properties = <P> {};
this._diffPropertyFunctionMap = new Map<string, string>();
this.nodeHandler = new NodeHandler();
this._bindFunctionPropertyMap = new WeakMap<(...args: any[]) => any, { boundFunc: (...args: any[]) => any, scope: any }>();
this._registry = new RegistryHandler();
this._nodeHandler = new NodeHandler();
this.own(this._registry);
this.own(this._nodeHandler);
this._boundRenderFunc = this.render.bind(this);
this._boundInvalidate = this.invalidate.bind(this);
this.own(this.on({
'element-created': ({ key, element }: WidgetAndElementEvent) => {
this._nodeHandler.add(element, `${key}`);
this.onElementCreated(element, key);
},
'element-updated': ({ key, element }: WidgetAndElementEvent) => {
this._nodeHandler.add(element, `${key}`);
this.onElementUpdated(element, key);
},
'widget-created': ({ element }: WidgetAndElementEvent) => {
this._nodeHandler.addRoot(element, undefined);
},
'widget-updated': ({ element }: WidgetAndElementEvent) => {
this._nodeHandler.addRoot(element, undefined);
}
}));
this.own(this._registry.on('invalidate', this._boundInvalidate));
this._registry.on('invalidate', this._boundInvalidate);
}

protected meta<T extends WidgetMetaBase>(MetaType: WidgetMetaConstructor<T>): T {
let cached = this._metaMap.get(MetaType);
if (!cached) {
cached = new MetaType({
invalidate: this._boundInvalidate,
nodeHandler: this._nodeHandler,
nodeHandler: this.nodeHandler,
bind: this
});
this._metaMap.set(MetaType, cached);
this.own(cached);
cached;
}

return cached as T;
Expand All @@ -171,7 +150,7 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
* @param element The dom node represented by the vdom node.
* @param key The vdom node's key.
*/
protected onElementCreated(element: Element, key: string): void {
public onElementCreated(element: Element, key: string): void {
// Do nothing by default.
}

Expand All @@ -181,7 +160,7 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
* @param element The dom node represented by the vdom node.
* @param key The vdom node's key.
*/
protected onElementUpdated(element: Element, key: string): void {
public onElementUpdated(element: Element, key: string): void {
// Do nothing by default.
}

Expand Down Expand Up @@ -286,7 +265,7 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
const render = this._runBeforeRenders();
let dNode = render();
this._cachedDNode = this.runAfterRenders(dNode);
this._nodeHandler.clear();
this.nodeHandler.clear();
}
this._renderState = WidgetRenderState.IDLE;
return this._cachedDNode;
Expand All @@ -295,10 +274,9 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
public invalidate(): void {
if (this._renderState === WidgetRenderState.IDLE) {
this._dirty = true;
this.emit({
type: 'invalidated',
target: this
});
if (this.parentInvalidate) {
this.parentInvalidate();
}
}
else if (this._renderState === WidgetRenderState.PROPERTIES) {
this._dirty = true;
Expand Down Expand Up @@ -476,7 +454,7 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
}, dNode);
}

this._metaMap.forEach(meta => {
this._metaMap.forEach((meta) => {
meta.afterRender();
});

Expand Down
2 changes: 1 addition & 1 deletion src/decorators/inject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function inject({ name, getProperties }: InjectConfig) {
}
if (registeredInjectors.indexOf(injector) === -1) {
injector.on('invalidate', () => {
this.emit({ type: 'invalidated', target: this });
this.invalidate();
});
registeredInjectors.push(injector);
}
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ export interface DefaultWidgetBaseInterface extends WidgetBaseInterface<WidgetPr
*/
export interface WidgetBaseInterface<
P = WidgetProperties,
C extends DNode = DNode> extends Evented {
C extends DNode = DNode> {

/**
* Widget properties
Expand Down
7 changes: 1 addition & 6 deletions src/mixins/I18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,13 @@ export function I18nMixin<T extends Constructor<WidgetBase<any>>>(Base: T): T &

constructor(...args: any[]) {
super(...args);
const subscription = observeLocale({
observeLocale({
next: () => {
if (!this.properties.locale) {
this.invalidate();
}
}
});
this.own({
destroy() {
subscription.unsubscribe();
}
});
}

public localizeBundle<T extends Messages>(bundle: Bundle<T>): LocalizedMessages<T> {
Expand Down
66 changes: 38 additions & 28 deletions src/mixins/Projector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { assign } from '@dojo/core/lang';
import global from '@dojo/shim/global';
import { createHandle } from '@dojo/core/lang';
import { Handle } from '@dojo/interfaces/core';
import { Evented } from '@dojo/core/Evented';
import 'pepjs';
import cssTransitions from '../animations/cssTransitions';
import { Constructor, DNode, Projection, ProjectionOptions } from './../interfaces';
Expand Down Expand Up @@ -87,7 +86,7 @@ export interface ProjectorMixin<P> {
* The `Projector` creates a `DocumentFragment` which replaces any other `root` that has been set.
* @param doc The `Document` to use, which defaults to the global `document`.
*/
sandbox(doc?: Document): Handle;
sandbox(doc?: Document): void;

/**
* Schedule a render.
Expand Down Expand Up @@ -133,6 +132,11 @@ export interface ProjectorMixin<P> {
* Exposes invalidate for projector instances
*/
invalidate(): void;

/**
* Runs registered destroy handles
*/
destroy(): void;
}

export function ProjectorMixin<P, T extends Constructor<WidgetBase<P>>>(Base: T): T & Constructor<ProjectorMixin<P>> {
Expand All @@ -154,28 +158,23 @@ export function ProjectorMixin<P, T extends Constructor<WidgetBase<P>>>(Base: T)
private _projectorProperties: this['properties'] = {} as this['properties'];
private _rootTagName: string;
private _attachType: AttachType;
private _handles: Function[] = [];

constructor(...args: any[]) {
super(...args);

const nodeEvent = new Evented();
this.own(nodeEvent);

this.parentInvalidate = this.scheduleRender.bind(this);
this._projectionOptions = {
transitions: cssTransitions
};

this._boundDoRender = this._doRender.bind(this);
this._boundRender = this.__render__.bind(this);
this.own(this.on('invalidated', () => {
this.scheduleRender();
}));

this.root = document.body;
this.projectorState = ProjectorAttachState.Detached;
}

public append(root?: Element) {
public append(root?: Element): Handle {
const options = {
type: AttachType.Append,
root
Expand All @@ -184,7 +183,7 @@ export function ProjectorMixin<P, T extends Constructor<WidgetBase<P>>>(Base: T)
return this._attach(options);
}

public merge(root?: Element) {
public merge(root?: Element): Handle {
const options = {
type: AttachType.Merge,
root
Expand All @@ -193,7 +192,7 @@ export function ProjectorMixin<P, T extends Constructor<WidgetBase<P>>>(Base: T)
return this._attach(options);
}

public replace(root?: Element) {
public replace(root?: Element): Handle {
const options = {
type: AttachType.Replace,
root
Expand Down Expand Up @@ -252,18 +251,19 @@ export function ProjectorMixin<P, T extends Constructor<WidgetBase<P>>>(Base: T)
this._async = async;
}

public sandbox(doc: Document = document): Handle {
public sandbox(doc: Document = document): void {
if (this.projectorState === ProjectorAttachState.Attached) {
throw new Error('Projector already attached, cannot create sandbox');
}
this._async = false;
const previousRoot = this.root;

/* free up the document fragment for GC */
this.own(createHandle(() => {
this.own(() => {
this._root = previousRoot;
}));
return this._attach({
});

this._attach({
/* DocumentFragment is not assignable to Element, but provides everything needed to work */
root: doc.createDocumentFragment() as any,
type: AttachType.Append
Expand All @@ -290,9 +290,6 @@ export function ProjectorMixin<P, T extends Constructor<WidgetBase<P>>>(Base: T)
if (this._projectorProperties.registry) {
this._projectorProperties.registry.destroy();
}
if (properties.registry) {
this.own(properties.registry);
}
}
this._projectorProperties = assign({}, properties);
super.__setCoreProperties__({ bind: this, baseRegistry: properties.registry });
Expand Down Expand Up @@ -324,6 +321,19 @@ export function ProjectorMixin<P, T extends Constructor<WidgetBase<P>>>(Base: T)
}
}

private own(handle: Function): void {
this._handles.push(handle);
}

public destroy() {
while (this._handles.length > 0) {
const handle = this._handles.pop();
if (handle) {
handle();
}
}
}

private _attach({ type, root }: AttachOptions): Handle {
this._attachType = type;
if (root) {
Expand All @@ -336,16 +346,16 @@ export function ProjectorMixin<P, T extends Constructor<WidgetBase<P>>>(Base: T)

this.projectorState = ProjectorAttachState.Attached;

this._attachHandle = this.own({
destroy: () => {
if (this.projectorState === ProjectorAttachState.Attached) {
this.pause();
this._projection = undefined;
this.projectorState = ProjectorAttachState.Detached;
}
this._attachHandle = { destroy() { } };
const handle = () => {
if (this.projectorState === ProjectorAttachState.Attached) {
this.pause();
this._projection = undefined;
this.projectorState = ProjectorAttachState.Detached;
}
});
};

this.own(handle);
this._attachHandle = createHandle(handle);

this._projectionOptions = { ...this._projectionOptions, ...{ sync: !this._async } };

Expand Down
2 changes: 1 addition & 1 deletion src/util/DomWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function DomWrapper(domNode: Element, options: DomWrapperOptions = {}): D
return hNode;
}

protected onElementCreated(element: Element, key: string) {
public onElementCreated(element: Element, key: string) {
options.onAttached && options.onAttached();
}

Expand Down
Loading