import { VNode } from './vnode'; import options from './options'; const stack = []; const EMPTY_CHILDREN = []; /** * JSX/hyperscript reviver. * @see http://jasonformat.com/wtf-is-jsx * Benchmarks: https://esbench.com/bench/57ee8f8e330ab09900a1a1a0 * * Note: this is exported as both `h()` and `createElement()` for compatibility * reasons. * * Creates a VNode (virtual DOM element). A tree of VNodes can be used as a * lightweight representation of the structure of a DOM tree. This structure can * be realized by recursively comparing it against the current _actual_ DOM * structure, and applying only the differences. * * `h()`/`createElement()` accepts an element name, a list of attributes/props, * and optionally children to append to the element. * * @example The following DOM tree * * `
Hello!
` * * can be constructed using this function as: * * `h('div', { id: 'foo', name : 'bar' }, 'Hello!');` * * @param {string | function} nodeName An element name. Ex: `div`, `a`, `span`, etc. * @param {object | null} attributes Any attributes/props to set on the created element. * @param {VNode[]} [rest] Additional arguments are taken to be children to * append. Can be infinitely nested Arrays. * * @public */ export function h(nodeName, attributes) { let children=EMPTY_CHILDREN, lastSimple, child, simple, i; for (i=arguments.length; i-- > 2; ) { stack.push(arguments[i]); } if (attributes && attributes.children!=null) { if (!stack.length) stack.push(attributes.children); delete attributes.children; } while (stack.length) { if ((child = stack.pop()) && child.pop!==undefined) { for (i=child.length; i--; ) stack.push(child[i]); } else { if (typeof child==='boolean') child = null; if ((simple = typeof nodeName!=='function')) { if (child==null) child = ''; else if (typeof child==='number') child = String(child); else if (typeof child!=='string') simple = false; } if (simple && lastSimple) { children[children.length-1] += child; } else if (children===EMPTY_CHILDREN) { children = [child]; } else { children.push(child); } lastSimple = simple; } } let p = new VNode(); p.nodeName = nodeName; p.children = children; p.attributes = attributes==null ? undefined : attributes; p.key = attributes==null ? undefined : attributes.key; // if a "vnode hook" is defined, pass every created VNode to it if (options.vnode!==undefined) options.vnode(p); return p; }