1 | import 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 | */
|
11 | export 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 | */
|
60 | export 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 |
|
88 | export function createRef() {
|
89 | return {};
|
90 | }
|
91 |
|
92 | export 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 | */
|
101 | export const isValidElement = vnode =>
|
102 | vnode != null && vnode.constructor === undefined;
|