UNPKG

3.03 kBJavaScriptView Raw
1import options from './options';
2
3/**
4 * Create an virtual node (used for JSX)
5 * @param {import('./internal').VNode["type"]} type The node name or Component
6 * constructor for this virtual node
7 * @param {object | null | undefined} [props] The properties of the virtual node
8 * @param {Array<import('.').ComponentChildren>} [children] The children of the virtual node
9 * @returns {import('./internal').VNode}
10 */
11export function createElement(type, props, children) {
12 let normalizedProps = {},
13 i;
14 for (i in props) {
15 if (i !== 'key' && i !== 'ref') normalizedProps[i] = props[i];
16 }
17
18 if (arguments.length > 3) {
19 children = [children];
20 // https://github.com/preactjs/preact/issues/1916
21 for (i = 3; i < arguments.length; i++) {
22 children.push(arguments[i]);
23 }
24 }
25 if (children != null) {
26 normalizedProps.children = children;
27 }
28
29 // If a Component VNode, check for and apply defaultProps
30 // Note: type may be undefined in development, must never error here.
31 if (typeof type == 'function' && type.defaultProps != null) {
32 for (i in type.defaultProps) {
33 if (normalizedProps[i] === undefined) {
34 normalizedProps[i] = type.defaultProps[i];
35 }
36 }
37 }
38
39 return createVNode(
40 type,
41 normalizedProps,
42 props && props.key,
43 props && props.ref,
44 null
45 );
46}
47
48/**
49 * Create a VNode (used internally by Preact)
50 * @param {import('./internal').VNode["type"]} type The node name or Component
51 * Constructor for this virtual node
52 * @param {object | string | number | null} props The properties of this virtual node.
53 * If this virtual node represents a text node, this is the text of the node (string or number).
54 * @param {string | number | null} key The key for this virtual node, used when
55 * diffing it against its children
56 * @param {import('./internal').VNode["ref"]} ref The ref property that will
57 * receive a reference to its created child
58 * @returns {import('./internal').VNode}
59 */
60export function createVNode(type, props, key, ref, original) {
61 // V8 seems to be better at detecting type shapes if the object is allocated from the same call site
62 // Do not inline into createElement and coerceToVNode!
63 const vnode = {
64 type,
65 props,
66 key,
67 ref,
68 _children: null,
69 _parent: null,
70 _depth: 0,
71 _dom: null,
72 // _nextDom must be initialized to undefined b/c it will eventually
73 // be set to dom.nextSibling which can return `null` and it is important
74 // to be able to distinguish between an uninitialized _nextDom and
75 // a _nextDom that has been set to `null`
76 _nextDom: undefined,
77 _component: null,
78 constructor: undefined,
79 _original: original
80 };
81
82 if (original == null) vnode._original = vnode;
83 if (options.vnode) options.vnode(vnode);
84
85 return vnode;
86}
87
88export function createRef() {
89 return {};
90}
91
92export function Fragment(props) {
93 return props.children;
94}
95
96/**
97 * Check if a the argument is a valid Preact VNode.
98 * @param {*} vnode
99 * @returns {vnode is import('./internal').VNode}
100 */
101export const isValidElement = vnode =>
102 vnode != null && vnode.constructor === undefined;