@@ -11,18 +11,29 @@ import { insert } from './operations';
11
11
import { setProperty } from './props' ;
12
12
import { assign , isArray , slice } from '../util' ;
13
13
import options from '../options' ;
14
+ import {
15
+ createInternal ,
16
+ MODE_MATH ,
17
+ MODE_SVG ,
18
+ TYPE_CLASS ,
19
+ TYPE_COMPONENT ,
20
+ TYPE_ELEMENT ,
21
+ TYPE_FUNCTION ,
22
+ TYPE_INVALID ,
23
+ TYPE_TEXT
24
+ } from '../tree' ;
14
25
15
26
/**
16
27
* Diff two virtual nodes and apply proper changes to the DOM
17
- * @param {PreactElement } parentDom The parent of the DOM element
18
- * @param {VNode } newVNode The new virtual node
28
+ * @param {import('../internal'). PreactElement } parentDom The parent of the DOM element
29
+ * @param {import('../internal').Internal } internal The backing node.
19
30
* @param {object } globalContext The current context object. Modified by
20
31
* getChildContext
21
32
* @param {string } namespace Current namespace of the DOM node (HTML, SVG, or MathML)
22
- * @param {Array<PreactElement> } excessDomChildren
23
- * @param {Array<Component> } commitQueue List of components which have callbacks
33
+ * @param {Array<import('../internal'). PreactElement> } excessDomChildren
34
+ * @param {Array<import('../internal'). Component> } commitQueue List of components which have callbacks
24
35
* to invoke in commitRoot
25
- * @param {PreactElement } oldDom The current attached DOM element any new dom
36
+ * @param {import('../internal'). PreactElement } oldDom The current attached DOM element any new dom
26
37
* elements should be placed around. Likely `null` on first render (except when
27
38
* hydrating). Can be a sibling DOM element when diffing Fragments that have
28
39
* siblings. In most cases, it starts out as `oldChildren[0]._dom`.
@@ -31,7 +42,7 @@ import options from '../options';
31
42
*/
32
43
export function mount (
33
44
parentDom ,
34
- newVNode ,
45
+ internal ,
35
46
globalContext ,
36
47
namespace ,
37
48
excessDomChildren ,
@@ -40,22 +51,26 @@ export function mount(
40
51
isHydrating ,
41
52
refQueue
42
53
) {
54
+ // @ts -expect-error
55
+ const newVNode = internal . vnode ;
56
+
43
57
// When passing through createElement it assigns the object
44
58
// constructor as undefined. This to prevent JSON-injection.
45
- if ( newVNode . constructor !== UNDEFINED ) return null ;
59
+ if ( internal . flags & TYPE_INVALID ) return null ;
46
60
47
61
/** @type {any } */
48
- let tmp ,
49
- newType = newVNode . type ;
62
+ let tmp ;
50
63
51
64
if ( ( tmp = options . _diff ) ) tmp ( newVNode ) ;
52
65
53
- if ( typeof newType == 'function' ) {
66
+ if ( internal . flags & TYPE_COMPONENT ) {
54
67
try {
55
68
let c ,
56
- newProps = newVNode . props ;
57
- const isClassComponent =
58
- 'prototype' in newType && newType . prototype . render ;
69
+ newProps = internal . props ,
70
+ newType = /** @type {import('../internal').ComponentType } */ (
71
+ internal . type
72
+ ) ;
73
+ const isClassComponent = ! ! ( internal . flags & TYPE_CLASS ) ;
59
74
60
75
// Necessary for createContext api. Setting this property will pass
61
76
// the context value as `this.context` just for this component.
@@ -69,11 +84,17 @@ export function mount(
69
84
70
85
// Instantiate the new component
71
86
if ( isClassComponent ) {
72
- // @ts -expect-error The check above verifies that newType is suppose to be constructed
73
- newVNode . _component = c = new newType ( newProps , componentContext ) ; // eslint-disable-line new-cap
87
+ internal . _component =
88
+ newVNode . _component =
89
+ c =
90
+ // @ts -expect-error The check above verifies that newType is suppose to be constructed
91
+ new newType ( newProps , componentContext ) ; // eslint-disable-line new-cap
74
92
} else {
75
- // @ts -expect-error Trust me, Component implements the interface we want
76
- newVNode . _component = c = new BaseComponent ( newProps , componentContext ) ;
93
+ // @ts -expect-error The check above verifies that newType is suppose to be constructed
94
+ internal . _component =
95
+ newVNode . _component =
96
+ c =
97
+ new BaseComponent ( newProps , componentContext ) ;
77
98
c . constructor = newType ;
78
99
c . render = doRender ;
79
100
}
@@ -156,6 +177,7 @@ export function mount(
156
177
let renderResult = isTopLevelFragment ? tmp . props . children : tmp ;
157
178
158
179
oldDom = mountChildren (
180
+ internal ,
159
181
parentDom ,
160
182
isArray ( renderResult ) ? renderResult : [ renderResult ] ,
161
183
newVNode ,
@@ -200,7 +222,7 @@ export function mount(
200
222
}
201
223
} else {
202
224
oldDom = newVNode . _dom = mountElementNode (
203
- newVNode ,
225
+ internal ,
204
226
globalContext ,
205
227
namespace ,
206
228
excessDomChildren ,
@@ -217,43 +239,45 @@ export function mount(
217
239
218
240
/**
219
241
* Diff two virtual nodes representing DOM element
220
- * @param {VNode } newVNode The new virtual node
242
+ * @param {import('../internal').Internal } internal The new virtual node
221
243
* @param {object } globalContext The current context object
222
244
* @param {string } namespace Current namespace of the DOM node (HTML, SVG, or MathML)
223
- * @param {Array<PreactElement> } excessDomChildren
224
- * @param {Array<Component> } commitQueue List of components which have callbacks
245
+ * @param {Array<import('../internal'). PreactElement> } excessDomChildren
246
+ * @param {Array<import('../internal'). Component> } commitQueue List of components which have callbacks
225
247
* to invoke in commitRoot
226
248
* @param {boolean } isHydrating Whether or not we are in hydration
227
249
* @param {any[] } refQueue an array of elements needed to invoke refs
228
- * @returns {PreactElement }
250
+ * @returns {import('../internal'). PreactElement }
229
251
*/
230
252
function mountElementNode (
231
- newVNode ,
253
+ internal ,
232
254
globalContext ,
233
255
namespace ,
234
256
excessDomChildren ,
235
257
commitQueue ,
236
258
isHydrating ,
237
259
refQueue
238
260
) {
239
- /** @type {PreactElement } */
261
+ // @ts -expect-error
262
+ const newVNode = internal . vnode ;
263
+ /** @type {import('../internal').PreactElement } */
240
264
let dom ;
241
265
let oldProps = EMPTY_OBJ ;
242
- let newProps = newVNode . props ;
243
- let nodeType = /** @type {string } */ ( newVNode . type ) ;
266
+ let newProps = internal . props ;
267
+ let nodeType = /** @type {string } */ ( internal . type ) ;
244
268
/** @type {any } */
245
269
let i ;
246
270
/** @type {{ __html?: string } } */
247
271
let newHtml ;
248
- /** @type {ComponentChildren } */
272
+ /** @type {import('../internal'). ComponentChildren } */
249
273
let newChildren ;
250
274
let value ;
251
275
let inputValue ;
252
276
let checked ;
253
277
254
278
// Tracks entering and exiting namespaces when descending through the tree.
255
- if ( nodeType === 'svg' ) namespace = 'http://www.w3.org/2000/svg' ;
256
- else if ( nodeType === 'math' )
279
+ if ( internal . flags & MODE_SVG ) namespace = 'http://www.w3.org/2000/svg' ;
280
+ else if ( internal . flags & MODE_MATH )
257
281
namespace = 'http://www.w3.org/1998/Math/MathML' ;
258
282
else if ( ! namespace ) namespace = 'http://www.w3.org/1999/xhtml' ;
259
283
@@ -277,7 +301,7 @@ function mountElementNode(
277
301
}
278
302
279
303
if ( dom == null ) {
280
- if ( nodeType === null ) {
304
+ if ( internal . flags & TYPE_TEXT ) {
281
305
return document . createTextNode ( newProps ) ;
282
306
}
283
307
@@ -298,7 +322,7 @@ function mountElementNode(
298
322
excessDomChildren = null ;
299
323
}
300
324
301
- if ( nodeType === null ) {
325
+ if ( internal . flags & TYPE_TEXT ) {
302
326
// During hydration, we still have to split merged text from SSR'd HTML.
303
327
dom . data = newProps ;
304
328
} else {
@@ -361,6 +385,7 @@ function mountElementNode(
361
385
newVNode . _children = [ ] ;
362
386
} else {
363
387
mountChildren (
388
+ internal ,
364
389
dom ,
365
390
isArray ( newChildren ) ? newChildren : [ newChildren ] ,
366
391
newVNode ,
@@ -416,25 +441,27 @@ function doRender(props, _state, context) {
416
441
417
442
/**
418
443
* Diff the children of a virtual node
419
- * @param {PreactElement } parentDom The DOM element whose children are being
444
+ * @param {import('../internal').Internal } internal The DOM element whose children are being
445
+ * @param {import('../internal').PreactElement } parentDom The DOM element whose children are being
420
446
* diffed
421
- * @param {ComponentChildren[] } renderResult
422
- * @param {VNode } newParentVNode The new virtual node whose children should be
447
+ * @param {import('../internal'). ComponentChildren[] } renderResult
448
+ * @param {import('../internal'). VNode } newParentVNode The new virtual node whose children should be
423
449
* diff'ed against oldParentVNode
424
450
* @param {object } globalContext The current context object - modified by
425
451
* getChildContext
426
452
* @param {string } namespace Current namespace of the DOM node (HTML, SVG, or MathML)
427
- * @param {Array<PreactElement> } excessDomChildren
428
- * @param {Array<Component> } commitQueue List of components which have callbacks
453
+ * @param {Array<import('../internal'). PreactElement> } excessDomChildren
454
+ * @param {Array<import('../internal'). Component> } commitQueue List of components which have callbacks
429
455
* to invoke in commitRoot
430
- * @param {PreactElement } oldDom The current attached DOM element any new dom
456
+ * @param {import('../internal'). PreactElement } oldDom The current attached DOM element any new dom
431
457
* elements should be placed around. Likely `null` on first render (except when
432
458
* hydrating). Can be a sibling DOM element when diffing Fragments that have
433
459
* siblings. In most cases, it starts out as `oldChildren[0]._dom`.
434
460
* @param {boolean } isHydrating Whether or not we are in hydration
435
461
* @param {any[] } refQueue an array of elements needed to invoke refs
436
462
*/
437
463
function mountChildren (
464
+ internal ,
438
465
parentDom ,
439
466
renderResult ,
440
467
newParentVNode ,
@@ -447,11 +474,11 @@ function mountChildren(
447
474
refQueue
448
475
) {
449
476
let i ,
450
- /** @type {VNode } */
477
+ /** @type {import('../internal'). VNode } */
451
478
childVNode ,
452
- /** @type {PreactElement } */
479
+ /** @type {import('../internal'). PreactElement } */
453
480
newDom ,
454
- /** @type {PreactElement } */
481
+ /** @type {import('../internal'). PreactElement } */
455
482
firstChildDom ;
456
483
457
484
let newChildrenLength = renderResult . length ;
@@ -517,10 +544,11 @@ function mountChildren(
517
544
childVNode . _parent = newParentVNode ;
518
545
childVNode . _depth = newParentVNode . _depth + 1 ;
519
546
547
+ const childInternal = createInternal ( childVNode , internal ) ;
520
548
// Morph the old element into the new one, but don't append it to the dom yet
521
549
const result = mount (
522
550
parentDom ,
523
- childVNode ,
551
+ childInternal ,
524
552
globalContext ,
525
553
namespace ,
526
554
excessDomChildren ,
@@ -544,9 +572,13 @@ function mountChildren(
544
572
firstChildDom = newDom ;
545
573
}
546
574
547
- if ( typeof childVNode . type != 'function' ) {
575
+ if ( childInternal . flags & TYPE_ELEMENT || childInternal . flags & TYPE_TEXT ) {
548
576
oldDom = insert ( childVNode , oldDom , parentDom ) ;
549
- } else if ( typeof childVNode . type == 'function' && result !== UNDEFINED ) {
577
+ } else if (
578
+ ( childInternal . flags & TYPE_FUNCTION ||
579
+ childInternal . flags & TYPE_CLASS ) &&
580
+ result !== UNDEFINED
581
+ ) {
550
582
oldDom = result ;
551
583
} else if ( newDom ) {
552
584
oldDom = newDom . nextSibling ;
0 commit comments