Skip to content

Commit

Permalink
docs(vdom): add JSDoc comments for a few virtual DOM related things (#…
Browse files Browse the repository at this point in the history
…3931)

This adds JSDoc comments explaining (what I believe to be) the purpose
of a few functions in `h.ts` and `vdom-render.ts`.
  • Loading branch information
alicewriteswrongs authored Jan 18, 2023
1 parent 621ce8e commit ae7610a
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 1 deletion.
11 changes: 11 additions & 0 deletions src/declarations/stencil-public-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,14 @@ export interface FunctionalComponent<T = {}> {
(props: T, children: VNode[], utils: FunctionalUtilities): VNode | VNode[];
}

/**
* A Child VDOM node
*
* This has most of the same properties as {@link VNode} but friendlier names
* (i.e. `vtag` instead of `$tag$`, `vchildren` instead of `$children$`) in
* order to provide a friendlier public interface for users of the
* {@link FunctionalUtilities}).
*/
export interface ChildNode {
vtag?: string | number | Function;
vkey?: string | number;
Expand Down Expand Up @@ -607,6 +615,9 @@ export declare function h(sel: any, data: VNodeData | null, text: string): VNode
export declare function h(sel: any, data: VNodeData | null, children: Array<VNode | undefined | null>): VNode;
export declare function h(sel: any, data: VNodeData | null, children: VNode): VNode;

/**
* A virtual DOM node
*/
export interface VNode {
$flags$: number;
$tag$: string | number | Function;
Expand Down
31 changes: 31 additions & 0 deletions src/runtime/vdom/h.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ Empty objects can also be the cause, look for JSX comments that became objects.`
return vnode;
};

/**
* A utility function for creating a virtual DOM node from a tag and some
* possible text content.
*
* @param tag the tag for this element
* @param text possible text content for the node
* @returns a newly-minted virtual DOM node
*/
export const newVNode = (tag: string, text: string) => {
const vnode: d.VNode = {
$flags$: 0,
Expand All @@ -123,6 +131,12 @@ export const newVNode = (tag: string, text: string) => {

export const Host = {};

/**
* Check whether a given node is a Host node or not
*
* @param node the virtual DOM node to check
* @returns whether it's a Host node or not
*/
export const isHost = (node: any): node is d.VNode => node && node.$tag$ === Host;

/**
Expand All @@ -137,6 +151,13 @@ const vdomFnUtils: d.FunctionalUtilities = {
map: (children, cb) => children.map(convertToPublic).map(cb).map(convertToPrivate),
};

/**
* Convert a {@link d.VNode} to a {@link d.ChildNode} in order to present a
* friendlier public interface (hence, 'convertToPublic').
*
* @param node the virtual DOM node to convert
* @returns a converted child node
*/
const convertToPublic = (node: d.VNode): d.ChildNode => ({
vattrs: node.$attrs$,
vchildren: node.$children$,
Expand All @@ -146,6 +167,15 @@ const convertToPublic = (node: d.VNode): d.ChildNode => ({
vtext: node.$text$,
});

/**
* Convert a {@link d.ChildNode} back to an equivalent {@link d.VNode} in
* order to use the resulting object in the virtual DOM. The initial object was
* likely created as part of presenting a public API, so converting it back
* involved making it 'private' again (hence, `convertToPrivate`).
*
* @param node the child node to convert
* @returns a converted virtual DOM node
*/
const convertToPrivate = (node: d.ChildNode): d.VNode => {
if (typeof node.vtag === 'function') {
const vnodeData = { ...node.vattrs };
Expand All @@ -171,6 +201,7 @@ const convertToPrivate = (node: d.ChildNode): d.VNode => {

/**
* Validates the ordering of attributes on an input element
*
* @param inputElm the element to validate
*/
const validateInputProperties = (inputElm: HTMLInputElement): void => {
Expand Down
43 changes: 42 additions & 1 deletion src/runtime/vdom/vdom-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,21 @@ const putBackInOriginalLocation = (parentElm: Node, recursive: boolean) => {
plt.$flags$ &= ~PLATFORM_FLAGS.isTmpDisconnected;
};

/**
* Create DOM nodes corresponding to a list of {@link d.Vnode} objects and
* add them to the DOM in the appropriate place.
*
* @param parentElm the DOM node which should be used as a parent for the new
* DOM nodes
* @param before a child of the `parentElm` which the new children should be
* inserted before (optional)
* @param parentVNode the parent virtual DOM node
* @param vnodes the new child virtual DOM nodes to produce DOM nodes for
* @param startIdx the index in the child virtual DOM nodes at which to start
* creating DOM nodes (inclusive)
* @param endIdx the index in the child virtual DOM nodes at which to stop
* creating DOM nodes (inclusive)
*/
const addVnodes = (
parentElm: d.RenderNode,
before: d.RenderNode,
Expand All @@ -217,6 +232,19 @@ const addVnodes = (
}
};

/**
* Remove the DOM elements corresponding to a list of {@link d.VNode} objects.
* This can be used to, for instance, clean up after a list of children which
* should no longer be shown.
*
* This function also handles some of Stencil's slot relocation logic.
*
* @param vnodes a list of virtual DOM nodes to remove
* @param startIdx the index at which to start removing nodes (inclusive)
* @param endIdx the index at which to stop removing nodes (inclusive)
* @param vnode a VNode
* @param elm an element
*/
const removeVnodes = (vnodes: d.VNode[], startIdx: number, endIdx: number, vnode?: d.VNode, elm?: d.RenderNode) => {
for (; startIdx <= endIdx; ++startIdx) {
if ((vnode = vnodes[startIdx])) {
Expand Down Expand Up @@ -503,7 +531,8 @@ const updateChildren = (parentElm: d.RenderNode, oldCh: d.VNode[], newVNode: d.V
*
* So, in other words, if `key` attrs are not set on VNodes which may be
* changing order within a `children` array or something along those lines then
* we could obtain a false positive and then have to do needless re-rendering.
* we could obtain a false negative and then have to do needless re-rendering
* (i.e. we'd say two VNodes aren't equal when in fact they should be).
*
* @param leftVNode the first VNode to check
* @param rightVNode the second VNode to check
Expand Down Expand Up @@ -761,6 +790,18 @@ interface RelocateNodeData {
$nodeToRelocate$: d.RenderNode;
}

/**
* The main entry point for Stencil's virtual DOM-based rendering engine
*
* Given a {@link d.HostRef} container and some virtual DOM nodes, this
* function will handle creating a virtual DOM tree with a single root, patching
* the current virtual DOM tree onto an old one (if any), dealing with slot
* relocation, and reflecting attributes.
*
* @param hostRef data needed to root and render the virtual DOM tree, such as
* the DOM node into which it should be rendered.
* @param renderFnResults the virtual DOM nodes to be rendered
*/
export const renderVdom = (hostRef: d.HostRef, renderFnResults: d.VNode | d.VNode[]) => {
const hostElm = hostRef.$hostElement$;
const cmpMeta = hostRef.$cmpMeta$;
Expand Down

0 comments on commit ae7610a

Please sign in to comment.