Skip to content
This repository has been archived by the owner on Nov 6, 2019. It is now read-only.

Commit

Permalink
made implementation of hpass more robust; now prevents sibling clobbe…
Browse files Browse the repository at this point in the history
…ring

still need to figure out how to handle cleanup; current implementation likely
causes a memory leak due to uncleaned-up React components
  • Loading branch information
telamonian committed Oct 14, 2019
1 parent 25d5dfa commit 192025a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 54 deletions.
66 changes: 23 additions & 43 deletions packages/virtualdom/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -748,10 +748,7 @@ class VirtualElement {
}

export
class VirtualElementPass {
readonly realize: VirtualElementPass.IRealize;

readonly render: VirtualElementPass.IRender;
class VirtualElementPass{

/**
* The type of the node.
Expand All @@ -764,26 +761,13 @@ class VirtualElementPass {
/**
* Construct a new virtual element pass thru node.
*
* @param realize - a function that takes no arguments and returns an HTMLElement
*
* @param render - a function that takes a host HTMLElement and returns void
*/
constructor({realize, render}: VirtualElementPass.IProps) {
this.render = render;
this.realize = realize || (() => {const host = document.createElement('div'); this.render(host); return host});
}
constructor(readonly render: VirtualElementPass.IRender, readonly tag: string, readonly attrs: ElementAttrs) {}
}

export namespace VirtualElementPass {
export type IRealize = () => HTMLElement;

export type IRender = (host: HTMLElement) => void;

export interface IProps {
realize?: IRealize;

render: IRender;
}
}

/**
Expand Down Expand Up @@ -973,8 +957,8 @@ namespace h {
export const wbr: IFactory = h.bind(undefined, 'wbr');
}

export function hpass(props: VirtualElementPass.IProps): VirtualElementPass {
return new VirtualElementPass(props);
export function hpass(render: VirtualElementPass.IRender, tag: string, attrs: ElementAttrs = {}): VirtualElementPass {
return new VirtualElementPass(render, tag, attrs);
}

/**
Expand Down Expand Up @@ -1070,32 +1054,28 @@ namespace Private {
let host = arguments[1] || null;
const before = arguments[2] || null;

if (node.type === 'passthru') {
if (host) {
// TODO: figure out how to do an "insert before" with a passthru node
node.render(host);
} else {
throw new Error("createDOMNode should not be called with only one argument on vdom nodes of type === 'passthru'");
}
if (host) {
host.insertBefore(createDOMNode(node), before);
} else {
if (host) {
host.insertBefore(createDOMNode(node), before);
} else {
// Create a text node for a virtual text node.
if (node.type === 'text') {
return document.createTextNode(node.content);
}
// Create a text node for a virtual text node.
if (node.type === 'text') {
return document.createTextNode(node.content);
}

// Create the HTML element with the specified tag.
host = document.createElement(node.tag);
// Create the HTML element with the specified tag.
host = document.createElement(node.tag);

// Add the attributes for the new element.
addAttrs(host, node.attrs);
// Add the attributes for the new element.
addAttrs(host, node.attrs);

// Recursively populate the element with child content.
for (let i = 0, n = node.children.length; i < n; ++i) {
createDOMNode(node.children[i], host);
}
if (node.type === 'passthru') {
node.render(host);
return host;
}

// Recursively populate the element with child content.
for (let i = 0, n = node.children.length; i < n; ++i) {
createDOMNode(node.children[i], host);
}
}

Expand Down Expand Up @@ -1155,7 +1135,7 @@ namespace Private {

// Handle the case of passthru update.
if (oldVNode.type === 'passthru' && newVNode.type === 'passthru') {
newVNode.render(host);
newVNode.render(currElem as HTMLElement);
currElem = currElem!.nextSibling;
continue;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/widgets/src/tabbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1341,8 +1341,8 @@ namespace TabBar {
const { title } = data;
let className = this.createIconClass(data);

if (title.iconPass) {
return hpass(title.iconPass);
if (title.iconRender) {
return hpass(title.iconRender, 'div');
} else {
return h.div({className}, data.title.iconLabel);
}
Expand Down
18 changes: 9 additions & 9 deletions packages/widgets/src/title.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ class Title<T> {
if (options.iconLabel !== undefined) {
this._iconLabel = options.iconLabel;
}
if (options.iconPass !== undefined) {
this._iconPass = options.iconPass;
if (options.iconRender !== undefined) {
this._iconRender = options.iconRender;
}
if (options.caption !== undefined) {
this._caption = options.caption;
Expand Down Expand Up @@ -175,15 +175,15 @@ class Title<T> {
this._changed.emit(undefined);
}

get iconPass(): VirtualElementPass.IProps {
return this._iconPass;
get iconRender(): VirtualElementPass.IRender {
return this._iconRender;
}

set iconPass(value: VirtualElementPass.IProps) {
if (this._iconPass === value) {
set iconRender(value: VirtualElementPass.IRender) {
if (this._iconRender === value) {
return;
}
this._iconPass = value;
this._iconRender = value;
this._changed.emit(undefined);
}

Expand Down Expand Up @@ -285,7 +285,7 @@ class Title<T> {
private _mnemonic = -1;
private _iconClass = '';
private _iconLabel = '';
private _iconPass: VirtualElementPass.IProps;
private _iconRender: VirtualElementPass.IRender;
private _className = '';
private _closable = false;
private _dataset: Title.Dataset;
Expand Down Expand Up @@ -339,7 +339,7 @@ namespace Title {
*/
iconLabel?: string;

iconPass?: VirtualElementPass.IProps;
iconRender?: VirtualElementPass.IRender;

/**
* The caption for the title.
Expand Down

0 comments on commit 192025a

Please sign in to comment.