@simpreact/simpreact 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compat/context.d.ts +8 -0
- package/compat/context.js +7 -0
- package/compat/core.d.ts +43 -0
- package/compat/core.js +90 -0
- package/compat/dom.d.ts +11 -0
- package/compat/dom.js +10 -0
- package/compat/hooks.d.ts +24 -0
- package/compat/hooks.js +75 -0
- package/compat/index.d.ts +43 -0
- package/compat/index.js +17 -0
- package/compat/jsx-runtime.d.ts +10 -0
- package/compat/jsx-runtime.js +9 -0
- package/context/index.d.ts +24 -0
- package/context/index.js +64 -0
- package/core/createElement.d.ts +6 -9
- package/core/createElement.js +4 -25
- package/core/index.d.ts +4 -23
- package/core/index.js +3 -3
- package/core/internal.d.ts +1 -1
- package/core/internal.js +1 -1
- package/core/lifecycleEventBus.d.ts +4 -0
- package/core/memo.d.ts +10 -0
- package/core/memo.js +11 -0
- package/core/mounting.d.ts +6 -9
- package/core/mounting.js +44 -49
- package/core/patching.d.ts +4 -5
- package/core/patching.js +81 -68
- package/core/ref.d.ts +4 -4
- package/core/rerender.d.ts +7 -6
- package/core/rerender.js +91 -32
- package/core/unmounting.js +7 -3
- package/dom/attach-element-to-dom.js +11 -2
- package/dom/events.d.ts +9 -1
- package/dom/events.js +21 -5
- package/dom/props/controlled/input.js +5 -5
- package/dom/props/controlled/select.js +3 -3
- package/dom/props/controlled/textarea.js +5 -5
- package/dom/props/style.js +6 -3
- package/dom/render.js +3 -3
- package/hooks/index.d.ts +7 -3
- package/hooks/index.js +46 -14
- package/package.json +7 -1
- package/shared/index.d.ts +6 -0
- package/shared/index.js +12 -3
- package/shared/utils.d.ts +2 -0
- package/shared/utils.js +36 -0
- package/core/context.d.ts +0 -18
- package/core/context.js +0 -18
package/core/memo.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { shallowEqual } from '../shared/index.js';
|
|
2
|
+
export function memo(Component, compare = shallowEqual) {
|
|
3
|
+
const Memoized = (props => Component(props));
|
|
4
|
+
Memoized._isMemo = true;
|
|
5
|
+
Memoized._render = Component;
|
|
6
|
+
Memoized._compare = compare;
|
|
7
|
+
return Memoized;
|
|
8
|
+
}
|
|
9
|
+
export function isMemo(type) {
|
|
10
|
+
return type._isMemo;
|
|
11
|
+
}
|
package/core/mounting.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import type { Maybe, Nullable } from '../shared/index.js';
|
|
2
2
|
import type { HostReference } from './hostAdapter.js';
|
|
3
3
|
import type { SimpElement } from './createElement.js';
|
|
4
|
-
|
|
5
|
-
export declare function mount(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>, contextMap: Nullable<SimpContextMap>, hostNamespace: Maybe<string>): void;
|
|
4
|
+
export declare function mount(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>, context: unknown, hostNamespace: Maybe<string>): void;
|
|
6
5
|
export declare function mountTextElement(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>): void;
|
|
7
|
-
export declare function mountHostElement(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>,
|
|
8
|
-
export declare function mountFunctionalElement(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>,
|
|
9
|
-
export declare function mountFragment(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>,
|
|
10
|
-
export declare function mountArrayChildren(children: SimpElement[], reference: Nullable<HostReference>, nextReference: Nullable<HostReference>,
|
|
11
|
-
export declare function
|
|
12
|
-
export declare function mountConsumer(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>, contextMap: Nullable<SimpContextMap>, hostNamespace: Maybe<string>): void;
|
|
13
|
-
export declare function mountPortal(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>, contextMap: Nullable<SimpContextMap>): void;
|
|
6
|
+
export declare function mountHostElement(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>, context: unknown, hostNamespace: Maybe<string>): void;
|
|
7
|
+
export declare function mountFunctionalElement(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>, context: unknown, hostNamespace: Maybe<string>): void;
|
|
8
|
+
export declare function mountFragment(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>, context: unknown, hostNamespace: Maybe<string>): void;
|
|
9
|
+
export declare function mountArrayChildren(children: SimpElement[], reference: Nullable<HostReference>, nextReference: Nullable<HostReference>, context: unknown, parentElement: SimpElement, hostNamespace: Maybe<string>): void;
|
|
10
|
+
export declare function mountPortal(element: SimpElement, parentReference: Nullable<HostReference>, nextReference: Nullable<HostReference>, context: unknown): void;
|
package/core/mounting.js
CHANGED
|
@@ -1,29 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { emptyObject } from '../shared/index.js';
|
|
2
2
|
import { hostAdapter } from './hostAdapter.js';
|
|
3
3
|
import { createTextElement, normalizeRoot } from './createElement.js';
|
|
4
4
|
import { applyRef } from './ref.js';
|
|
5
5
|
import { lifecycleEventBus } from './lifecycleEventBus.js';
|
|
6
|
-
|
|
6
|
+
import { batchingRerenderLocker } from './rerender.js';
|
|
7
|
+
export function mount(element, parentReference, nextReference, context, hostNamespace) {
|
|
7
8
|
if (element.flag === 'TEXT') {
|
|
8
9
|
mountTextElement(element, parentReference, nextReference);
|
|
9
10
|
}
|
|
10
11
|
else if (element.flag === 'HOST') {
|
|
11
|
-
mountHostElement(element, parentReference, nextReference,
|
|
12
|
+
mountHostElement(element, parentReference, nextReference, context, hostNamespace);
|
|
12
13
|
}
|
|
13
14
|
else if (element.flag === 'FC') {
|
|
14
|
-
mountFunctionalElement(element, parentReference, nextReference,
|
|
15
|
+
mountFunctionalElement(element, parentReference, nextReference, context, hostNamespace);
|
|
15
16
|
}
|
|
16
17
|
else if (element.flag === 'FRAGMENT') {
|
|
17
|
-
mountFragment(element, parentReference, nextReference,
|
|
18
|
-
}
|
|
19
|
-
else if (element.flag === 'PROVIDER') {
|
|
20
|
-
mountProvider(element, parentReference, nextReference, contextMap, hostNamespace);
|
|
21
|
-
}
|
|
22
|
-
else if (element.flag === 'PORTAL') {
|
|
23
|
-
mountPortal(element, parentReference, nextReference, contextMap);
|
|
18
|
+
mountFragment(element, parentReference, nextReference, context, hostNamespace);
|
|
24
19
|
}
|
|
25
20
|
else {
|
|
26
|
-
|
|
21
|
+
mountPortal(element, parentReference, nextReference, context);
|
|
27
22
|
}
|
|
28
23
|
}
|
|
29
24
|
export function mountTextElement(element, parentReference, nextReference) {
|
|
@@ -32,7 +27,7 @@ export function mountTextElement(element, parentReference, nextReference) {
|
|
|
32
27
|
hostAdapter.insertOrAppend(parentReference, reference, nextReference);
|
|
33
28
|
}
|
|
34
29
|
}
|
|
35
|
-
export function mountHostElement(element, parentReference, nextReference,
|
|
30
|
+
export function mountHostElement(element, parentReference, nextReference, context, hostNamespace) {
|
|
36
31
|
const hostNamespaces = hostAdapter.getHostNamespaces(element, hostNamespace);
|
|
37
32
|
hostNamespace = hostNamespaces?.self;
|
|
38
33
|
const hostReference = (element.reference = hostAdapter.createReference(element.type, hostNamespace));
|
|
@@ -40,11 +35,11 @@ export function mountHostElement(element, parentReference, nextReference, contex
|
|
|
40
35
|
// HOST element always has Maybe<Many<SimpElement>> children due to normalization process.
|
|
41
36
|
const children = element.children;
|
|
42
37
|
if (Array.isArray(children)) {
|
|
43
|
-
mountArrayChildren(children, hostReference, null,
|
|
38
|
+
mountArrayChildren(children, hostReference, null, context, element, hostNamespaces?.children);
|
|
44
39
|
}
|
|
45
40
|
else if (children) {
|
|
46
41
|
children.parent = element;
|
|
47
|
-
mount(children, hostReference, null,
|
|
42
|
+
mount(children, hostReference, null, context, hostNamespaces?.children);
|
|
48
43
|
}
|
|
49
44
|
if (element.props) {
|
|
50
45
|
hostAdapter.mountProps(hostReference, element, hostNamespace);
|
|
@@ -61,9 +56,9 @@ export function mountHostElement(element, parentReference, nextReference, contex
|
|
|
61
56
|
}
|
|
62
57
|
applyRef(element);
|
|
63
58
|
}
|
|
64
|
-
export function mountFunctionalElement(element, parentReference, nextReference,
|
|
65
|
-
if (
|
|
66
|
-
element.
|
|
59
|
+
export function mountFunctionalElement(element, parentReference, nextReference, context, hostNamespace) {
|
|
60
|
+
if (context) {
|
|
61
|
+
element.context = context;
|
|
67
62
|
}
|
|
68
63
|
if (element.unmounted) {
|
|
69
64
|
element.unmounted = false;
|
|
@@ -74,61 +69,61 @@ export function mountFunctionalElement(element, parentReference, nextReference,
|
|
|
74
69
|
}
|
|
75
70
|
// FC element always has Maybe<SimpElement> children due to normalization process.
|
|
76
71
|
let children;
|
|
72
|
+
let triedToRerenderUnsubscribe;
|
|
77
73
|
try {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
lifecycleEventBus.
|
|
74
|
+
let triedToRerender = false;
|
|
75
|
+
let rerenderCounter = 0;
|
|
76
|
+
triedToRerenderUnsubscribe = lifecycleEventBus.subscribe(event => {
|
|
77
|
+
if (event.type === 'triedToRerender' && event.element === element) {
|
|
78
|
+
triedToRerender = true;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
do {
|
|
82
|
+
triedToRerender = false;
|
|
83
|
+
if (++rerenderCounter >= 25) {
|
|
84
|
+
throw new Error('Too many re-renders.');
|
|
85
|
+
}
|
|
86
|
+
lifecycleEventBus.publish({ type: 'beforeRender', element, phase: 'mounting' });
|
|
87
|
+
batchingRerenderLocker.lock();
|
|
88
|
+
children = element.type(element.props || emptyObject);
|
|
89
|
+
batchingRerenderLocker.flush();
|
|
90
|
+
lifecycleEventBus.publish({ type: 'afterRender', element, phase: 'mounting' });
|
|
91
|
+
} while (triedToRerender);
|
|
92
|
+
children = normalizeRoot(children, false);
|
|
81
93
|
}
|
|
82
94
|
catch (error) {
|
|
83
95
|
lifecycleEventBus.publish({ type: 'errored', element, error, phase: 'mounting' });
|
|
84
96
|
return;
|
|
85
97
|
}
|
|
98
|
+
finally {
|
|
99
|
+
triedToRerenderUnsubscribe();
|
|
100
|
+
}
|
|
86
101
|
if (children) {
|
|
87
102
|
children.parent = element;
|
|
88
|
-
mount((element.children = children), parentReference, nextReference,
|
|
103
|
+
mount((element.children = children), parentReference, nextReference, element.context, hostNamespace);
|
|
89
104
|
}
|
|
90
105
|
lifecycleEventBus.publish({ type: 'mounted', element });
|
|
91
106
|
}
|
|
92
|
-
export function mountFragment(element, parentReference, nextReference,
|
|
107
|
+
export function mountFragment(element, parentReference, nextReference, context, hostNamespace) {
|
|
93
108
|
// FRAGMENT element always has Maybe<Many<SimpElement>> children due to normalization process.
|
|
94
109
|
if (Array.isArray(element.children)) {
|
|
95
|
-
mountArrayChildren(element.children, parentReference, nextReference,
|
|
110
|
+
mountArrayChildren(element.children, parentReference, nextReference, context, element, hostNamespace);
|
|
96
111
|
}
|
|
97
112
|
else if (element.children) {
|
|
98
113
|
element.children.parent = element;
|
|
99
|
-
mount(element.children, parentReference, nextReference,
|
|
114
|
+
mount(element.children, parentReference, nextReference, context, hostNamespace);
|
|
100
115
|
}
|
|
101
116
|
}
|
|
102
|
-
export function mountArrayChildren(children, reference, nextReference,
|
|
117
|
+
export function mountArrayChildren(children, reference, nextReference, context, parentElement, hostNamespace) {
|
|
103
118
|
for (const child of children) {
|
|
104
119
|
child.parent = parentElement;
|
|
105
|
-
mount(child, reference, nextReference,
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
export function mountProvider(element, parentReference, nextReference, contextMap, hostNamespace) {
|
|
109
|
-
contextMap = new Map(contextMap);
|
|
110
|
-
contextMap.set(element.type.context, element.props.value);
|
|
111
|
-
// PROVIDER element always has Maybe<Many<SimpElement>> children due to normalization process.
|
|
112
|
-
if (Array.isArray(element.children)) {
|
|
113
|
-
mountArrayChildren(element.children, parentReference, nextReference, contextMap, element, hostNamespace);
|
|
114
|
-
}
|
|
115
|
-
else if (element.children) {
|
|
116
|
-
element.children.parent = element;
|
|
117
|
-
mount(element.children, parentReference, nextReference, contextMap, hostNamespace);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
export function mountConsumer(element, parentReference, nextReference, contextMap, hostNamespace) {
|
|
121
|
-
const children = normalizeRoot(element.type(element.props || emptyObject, contextMap || emptyMap), false);
|
|
122
|
-
if (!children) {
|
|
123
|
-
return;
|
|
120
|
+
mount(child, reference, nextReference, context, hostNamespace);
|
|
124
121
|
}
|
|
125
|
-
children.parent = element;
|
|
126
|
-
mount((element.children = children), parentReference, nextReference, contextMap, hostNamespace);
|
|
127
122
|
}
|
|
128
|
-
export function mountPortal(element, parentReference, nextReference,
|
|
123
|
+
export function mountPortal(element, parentReference, nextReference, context) {
|
|
129
124
|
if (element.children) {
|
|
130
125
|
element.children.parent = element;
|
|
131
|
-
mount(element.children, element.ref, null,
|
|
126
|
+
mount(element.children, element.ref, null, context, hostAdapter.getHostNamespaces(element.children, undefined)?.self);
|
|
132
127
|
}
|
|
133
128
|
const placeHolderElement = createTextElement('');
|
|
134
129
|
mountTextElement(placeHolderElement, parentReference, nextReference);
|
package/core/patching.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { Maybe, Nullable } from '../shared/index.js';
|
|
2
2
|
import type { SimpElement } from './createElement.js';
|
|
3
3
|
import type { HostReference } from './hostAdapter.js';
|
|
4
|
-
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function patchKeyedChildren(prevChildren: SimpElement[], nextChildren: SimpElement[], parentReference: HostReference, nextReference: Nullable<HostReference>, contextMap: Nullable<SimpContextMap>, hostNamespace: Maybe<string>): void;
|
|
4
|
+
export declare function patch(prevElement: SimpElement, nextElement: SimpElement, parentReference: HostReference, nextReference: Nullable<HostReference>, context: unknown, hostNamespace: Maybe<string>): void;
|
|
5
|
+
export declare function patchPortal(prevElement: SimpElement, nextElement: SimpElement, context: unknown): void;
|
|
6
|
+
export declare function updateFunctionalComponent(element: SimpElement, parentReference: HostReference, nextReference: Nullable<HostReference>, context: unknown, hostNamespace: Maybe<string>): void;
|
|
7
|
+
export declare function patchKeyedChildren(prevChildren: SimpElement[], nextChildren: SimpElement[], parentReference: HostReference, nextReference: Nullable<HostReference>, context: unknown, hostNamespace: Maybe<string>): void;
|
|
9
8
|
export declare function findParentReferenceFromElement(element: SimpElement): Nullable<HostReference>;
|
|
10
9
|
export declare function findHostReferenceFromElement(element: SimpElement): Nullable<HostReference>;
|
package/core/patching.js
CHANGED
|
@@ -1,49 +1,45 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { emptyObject } from '../shared/index.js';
|
|
2
2
|
import { normalizeRoot } from './createElement.js';
|
|
3
3
|
import { hostAdapter } from './hostAdapter.js';
|
|
4
4
|
import { clearElementHostReference, remove, unmount } from './unmounting.js';
|
|
5
|
-
import { mount, mountArrayChildren } from './mounting.js';
|
|
5
|
+
import { mount, mountArrayChildren, mountFunctionalElement } from './mounting.js';
|
|
6
6
|
import { applyRef } from './ref.js';
|
|
7
7
|
import { lifecycleEventBus } from './lifecycleEventBus.js';
|
|
8
|
-
|
|
8
|
+
import { batchingRerenderLocker } from './rerender.js';
|
|
9
|
+
import { isMemo } from './memo.js';
|
|
10
|
+
export function patch(prevElement, nextElement, parentReference, nextReference, context, hostNamespace) {
|
|
9
11
|
if (prevElement.type !== nextElement.type || prevElement.key !== nextElement.key) {
|
|
10
|
-
replaceWithNewElement(prevElement, nextElement, parentReference,
|
|
12
|
+
replaceWithNewElement(prevElement, nextElement, parentReference, context, hostNamespace);
|
|
11
13
|
}
|
|
12
14
|
else if (nextElement.flag === 'HOST') {
|
|
13
|
-
patchHostElement(prevElement, nextElement,
|
|
15
|
+
patchHostElement(prevElement, nextElement, context, hostNamespace);
|
|
14
16
|
}
|
|
15
17
|
else if (nextElement.flag === 'FC') {
|
|
16
|
-
patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference,
|
|
18
|
+
patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, context, hostNamespace);
|
|
17
19
|
}
|
|
18
20
|
else if (nextElement.flag === 'TEXT') {
|
|
19
21
|
patchTextElement(prevElement, nextElement);
|
|
20
22
|
}
|
|
21
23
|
else if (nextElement.flag === 'FRAGMENT') {
|
|
22
|
-
patchFragment(prevElement, nextElement, parentReference,
|
|
23
|
-
}
|
|
24
|
-
else if (nextElement.flag === 'PROVIDER') {
|
|
25
|
-
patchProvider(prevElement, nextElement, parentReference, contextMap, hostNamespace);
|
|
26
|
-
}
|
|
27
|
-
else if (nextElement.flag === 'PORTAL') {
|
|
28
|
-
patchPortal(prevElement, nextElement, contextMap);
|
|
24
|
+
patchFragment(prevElement, nextElement, parentReference, context, hostNamespace);
|
|
29
25
|
}
|
|
30
26
|
else {
|
|
31
|
-
|
|
27
|
+
patchPortal(prevElement, nextElement, context);
|
|
32
28
|
}
|
|
33
29
|
}
|
|
34
|
-
function replaceWithNewElement(prevElement, nextElement, parentReference,
|
|
30
|
+
function replaceWithNewElement(prevElement, nextElement, parentReference, context, hostNamespace) {
|
|
35
31
|
unmount(prevElement);
|
|
36
32
|
nextElement.parent = prevElement.parent;
|
|
37
33
|
if (nextElement.flag === 'HOST' && prevElement.flag === 'HOST') {
|
|
38
|
-
mount(nextElement, null, null,
|
|
34
|
+
mount(nextElement, null, null, context, hostNamespace);
|
|
39
35
|
hostAdapter.replaceChild(parentReference, nextElement.reference, prevElement.reference);
|
|
40
36
|
}
|
|
41
37
|
else {
|
|
42
|
-
mount(nextElement, parentReference, findHostReferenceFromElement(prevElement),
|
|
38
|
+
mount(nextElement, parentReference, findHostReferenceFromElement(prevElement), context, hostNamespace);
|
|
43
39
|
clearElementHostReference(prevElement, parentReference);
|
|
44
40
|
}
|
|
45
41
|
}
|
|
46
|
-
function patchHostElement(prevElement, nextElement,
|
|
42
|
+
function patchHostElement(prevElement, nextElement, context, hostNamespace) {
|
|
47
43
|
if (prevElement.ref) {
|
|
48
44
|
nextElement.ref = prevElement.ref;
|
|
49
45
|
}
|
|
@@ -51,36 +47,70 @@ function patchHostElement(prevElement, nextElement, contextMap, hostNamespace) {
|
|
|
51
47
|
hostNamespace = hostNamespaces?.self;
|
|
52
48
|
nextElement.reference = prevElement.reference;
|
|
53
49
|
hostAdapter.attachElementToReference(nextElement, nextElement.reference);
|
|
54
|
-
patchChildren(prevElement.children || prevElement.props?.children, nextElement.children || nextElement.props?.children, nextElement.reference, null, nextElement,
|
|
50
|
+
patchChildren(prevElement.children || prevElement.props?.children, nextElement.children || nextElement.props?.children, nextElement.reference, null, nextElement, context, hostNamespaces?.children);
|
|
55
51
|
hostAdapter.patchProps(nextElement.reference, prevElement, nextElement, hostNamespace);
|
|
56
52
|
if (prevElement.className !== nextElement.className) {
|
|
57
53
|
hostAdapter.setClassname(nextElement.reference, nextElement.className, hostNamespace);
|
|
58
54
|
}
|
|
59
55
|
applyRef(nextElement);
|
|
60
56
|
}
|
|
61
|
-
function patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference,
|
|
62
|
-
|
|
57
|
+
function patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, context, hostNamespace) {
|
|
58
|
+
nextElement.store = prevElement.store || {};
|
|
59
|
+
nextElement.store.latestElement = nextElement;
|
|
63
60
|
if (hostNamespace) {
|
|
64
61
|
nextElement.store.hostNamespace = hostNamespace;
|
|
65
62
|
}
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
let forceRender = false;
|
|
64
|
+
if (prevElement.store?.forceRender) {
|
|
65
|
+
forceRender = true;
|
|
66
|
+
prevElement.store.forceRender = false;
|
|
68
67
|
}
|
|
68
|
+
if (prevElement.unmounted) {
|
|
69
|
+
mountFunctionalElement(nextElement, parentReference, nextReference, context, hostNamespace);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (!forceRender && isMemo(nextElement.type) && nextElement.type._compare(prevElement.props, nextElement.props)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
nextElement.context = prevElement.context || context;
|
|
76
|
+
// FC element always has Maybe<SimpElement> children due to normalization process.
|
|
69
77
|
let nextChildren;
|
|
78
|
+
let triedToRerenderUnsubscribe;
|
|
70
79
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
lifecycleEventBus.
|
|
80
|
+
let triedToRerender = false;
|
|
81
|
+
let rerenderCounter = 0;
|
|
82
|
+
triedToRerenderUnsubscribe = lifecycleEventBus.subscribe(event => {
|
|
83
|
+
if (event.type === 'triedToRerender' && event.element === nextElement) {
|
|
84
|
+
triedToRerender = true;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
do {
|
|
88
|
+
triedToRerender = false;
|
|
89
|
+
if (++rerenderCounter >= 25) {
|
|
90
|
+
throw new Error('Too many re-renders.');
|
|
91
|
+
}
|
|
92
|
+
lifecycleEventBus.publish({ type: 'beforeRender', element: nextElement, phase: 'updating' });
|
|
93
|
+
batchingRerenderLocker.lock();
|
|
94
|
+
nextChildren = nextElement.type(nextElement.props || emptyObject);
|
|
95
|
+
batchingRerenderLocker.flush();
|
|
96
|
+
lifecycleEventBus.publish({ type: 'afterRender', element: nextElement, phase: 'updating' });
|
|
97
|
+
} while (triedToRerender);
|
|
98
|
+
nextChildren = normalizeRoot(nextChildren, false);
|
|
74
99
|
}
|
|
75
100
|
catch (error) {
|
|
76
101
|
lifecycleEventBus.publish({ type: 'errored', element: nextElement, error, phase: 'updating' });
|
|
102
|
+
remove(prevElement, parentReference);
|
|
77
103
|
return;
|
|
78
104
|
}
|
|
105
|
+
finally {
|
|
106
|
+
triedToRerenderUnsubscribe();
|
|
107
|
+
}
|
|
108
|
+
// Keep prevElement's children reference when prev and next elements are identical to avoid reassignment.
|
|
79
109
|
const prevChildren = prevElement.children;
|
|
80
110
|
if (nextChildren) {
|
|
81
111
|
nextElement.children = nextChildren;
|
|
82
112
|
}
|
|
83
|
-
patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement,
|
|
113
|
+
patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, nextElement.context, hostNamespace);
|
|
84
114
|
lifecycleEventBus.publish({ type: 'updated', element: nextElement });
|
|
85
115
|
}
|
|
86
116
|
function patchTextElement(prevElement, nextElement) {
|
|
@@ -89,57 +119,41 @@ function patchTextElement(prevElement, nextElement) {
|
|
|
89
119
|
hostAdapter.setTextContent(nextElement.reference, nextElement.children);
|
|
90
120
|
}
|
|
91
121
|
}
|
|
92
|
-
function patchFragment(prevElement, nextElement, parentReference,
|
|
122
|
+
function patchFragment(prevElement, nextElement, parentReference, context, hostNamespace) {
|
|
93
123
|
let nextReference = null;
|
|
94
124
|
if (Array.isArray(prevElement.children) && !Array.isArray(nextElement.children) && nextElement.children) {
|
|
95
125
|
nextReference = hostAdapter.findNextSiblingReference(findHostReferenceFromElement(prevElement.children[prevElement.children.length - 1]));
|
|
96
126
|
}
|
|
97
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement,
|
|
127
|
+
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, context, hostNamespace);
|
|
98
128
|
}
|
|
99
|
-
function
|
|
100
|
-
let nextReference = null;
|
|
101
|
-
if (Array.isArray(prevElement.children) && !Array.isArray(nextElement.children) && nextElement.children) {
|
|
102
|
-
nextReference = hostAdapter.findNextSiblingReference(findHostReferenceFromElement(prevElement.children[prevElement.children.length - 1]));
|
|
103
|
-
}
|
|
104
|
-
contextMap = new Map(contextMap);
|
|
105
|
-
contextMap.set(nextElement.type.context, nextElement.props.value);
|
|
106
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, contextMap, hostNamespace);
|
|
107
|
-
}
|
|
108
|
-
function patchConsumer(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace) {
|
|
109
|
-
const children = normalizeRoot(nextElement.type(nextElement.props || emptyObject, contextMap || emptyMap), false);
|
|
110
|
-
if (children) {
|
|
111
|
-
nextElement.children = children;
|
|
112
|
-
}
|
|
113
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, contextMap, hostNamespace);
|
|
114
|
-
}
|
|
115
|
-
export function patchPortal(prevElement, nextElement, contextMap) {
|
|
129
|
+
export function patchPortal(prevElement, nextElement, context) {
|
|
116
130
|
const prevContainer = prevElement.ref;
|
|
117
131
|
const nextContainer = nextElement.ref;
|
|
118
132
|
const nextChildren = nextElement.children;
|
|
119
|
-
patchChildren(prevElement.children, nextChildren, prevContainer, null, nextElement,
|
|
133
|
+
patchChildren(prevElement.children, nextChildren, prevContainer, null, nextElement, context, hostAdapter.getHostNamespaces(nextChildren, undefined)?.self);
|
|
120
134
|
nextElement.reference = prevElement.reference;
|
|
121
135
|
if (prevContainer !== nextContainer && nextChildren != null) {
|
|
122
136
|
hostAdapter.removeChild(prevContainer, nextChildren.reference);
|
|
123
137
|
hostAdapter.appendChild(nextContainer, nextChildren.reference);
|
|
124
138
|
}
|
|
125
139
|
}
|
|
126
|
-
export function updateFunctionalComponent(element, parentReference, nextReference,
|
|
127
|
-
patchFunctionalComponent(element, element, parentReference, nextReference,
|
|
140
|
+
export function updateFunctionalComponent(element, parentReference, nextReference, context, hostNamespace) {
|
|
141
|
+
patchFunctionalComponent(element, element, parentReference, nextReference, context, hostNamespace);
|
|
128
142
|
}
|
|
129
|
-
function patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement,
|
|
143
|
+
function patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, context, hostNamespace) {
|
|
130
144
|
if (Array.isArray(prevChildren)) {
|
|
131
145
|
if (Array.isArray(nextChildren)) {
|
|
132
146
|
for (const child of nextChildren) {
|
|
133
147
|
child.parent = nextElement;
|
|
134
148
|
}
|
|
135
|
-
patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference,
|
|
149
|
+
patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
136
150
|
}
|
|
137
151
|
else if (typeof nextChildren === 'string') {
|
|
138
152
|
unmount(prevChildren);
|
|
139
153
|
hostAdapter.setTextContent(parentReference, nextChildren);
|
|
140
154
|
}
|
|
141
155
|
else if (nextChildren) {
|
|
142
|
-
patchKeyedChildren(prevChildren, [nextChildren], parentReference, nextReference,
|
|
156
|
+
patchKeyedChildren(prevChildren, [nextChildren], parentReference, nextReference, context, hostNamespace);
|
|
143
157
|
}
|
|
144
158
|
else {
|
|
145
159
|
unmount(prevChildren);
|
|
@@ -149,7 +163,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
|
|
|
149
163
|
else if (typeof prevChildren === 'string') {
|
|
150
164
|
if (Array.isArray(nextChildren)) {
|
|
151
165
|
hostAdapter.clearNode(parentReference);
|
|
152
|
-
mountArrayChildren(nextChildren, parentReference, nextReference,
|
|
166
|
+
mountArrayChildren(nextChildren, parentReference, nextReference, context, nextElement, hostNamespace);
|
|
153
167
|
}
|
|
154
168
|
else if (typeof nextChildren === 'string') {
|
|
155
169
|
if (prevChildren !== nextChildren) {
|
|
@@ -159,7 +173,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
|
|
|
159
173
|
else if (nextChildren) {
|
|
160
174
|
hostAdapter.clearNode(parentReference);
|
|
161
175
|
nextChildren.parent = nextElement;
|
|
162
|
-
mount(nextChildren, parentReference, nextReference,
|
|
176
|
+
mount(nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
163
177
|
}
|
|
164
178
|
else {
|
|
165
179
|
hostAdapter.clearNode(parentReference);
|
|
@@ -167,7 +181,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
|
|
|
167
181
|
}
|
|
168
182
|
else if (prevChildren) {
|
|
169
183
|
if (Array.isArray(nextChildren)) {
|
|
170
|
-
patchKeyedChildren([prevChildren], nextChildren, parentReference, nextReference,
|
|
184
|
+
patchKeyedChildren([prevChildren], nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
171
185
|
}
|
|
172
186
|
else if (typeof nextChildren === 'string') {
|
|
173
187
|
unmount(prevChildren);
|
|
@@ -175,27 +189,26 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
|
|
|
175
189
|
}
|
|
176
190
|
else if (nextChildren) {
|
|
177
191
|
nextChildren.parent = nextElement;
|
|
178
|
-
patch(prevChildren, nextChildren, parentReference, nextReference,
|
|
192
|
+
patch(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
179
193
|
}
|
|
180
194
|
else {
|
|
181
|
-
|
|
182
|
-
hostAdapter.clearNode(parentReference);
|
|
195
|
+
remove(prevChildren, parentReference);
|
|
183
196
|
}
|
|
184
197
|
}
|
|
185
198
|
else {
|
|
186
199
|
if (Array.isArray(nextChildren)) {
|
|
187
|
-
mountArrayChildren(nextChildren, parentReference, nextReference,
|
|
200
|
+
mountArrayChildren(nextChildren, parentReference, nextReference, context, nextElement, hostNamespace);
|
|
188
201
|
}
|
|
189
202
|
else if (typeof nextChildren === 'string') {
|
|
190
203
|
hostAdapter.setTextContent(parentReference, nextChildren);
|
|
191
204
|
}
|
|
192
205
|
else if (nextChildren) {
|
|
193
206
|
nextChildren.parent = nextElement;
|
|
194
|
-
mount(nextChildren, parentReference, nextReference,
|
|
207
|
+
mount(nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
195
208
|
}
|
|
196
209
|
}
|
|
197
210
|
}
|
|
198
|
-
export function patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference,
|
|
211
|
+
export function patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace) {
|
|
199
212
|
let prevStart = 0;
|
|
200
213
|
let nextStart = 0;
|
|
201
214
|
let prevEnd = prevChildren.length - 1;
|
|
@@ -204,21 +217,21 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
204
217
|
while (prevStart <= prevEnd &&
|
|
205
218
|
nextStart <= nextEnd &&
|
|
206
219
|
prevChildren[prevStart].key === nextChildren[nextStart].key) {
|
|
207
|
-
patch(prevChildren[prevStart], nextChildren[nextStart], parentReference, null,
|
|
220
|
+
patch(prevChildren[prevStart], nextChildren[nextStart], parentReference, null, context, hostNamespace);
|
|
208
221
|
prevStart++;
|
|
209
222
|
nextStart++;
|
|
210
223
|
}
|
|
211
224
|
// Step 2: Sync from end
|
|
212
225
|
while (prevStart <= prevEnd && nextStart <= nextEnd && prevChildren[prevEnd].key === nextChildren[nextEnd].key) {
|
|
213
|
-
patch(prevChildren[prevEnd], nextChildren[nextEnd], parentReference, null,
|
|
226
|
+
patch(prevChildren[prevEnd], nextChildren[nextEnd], parentReference, null, context, hostNamespace);
|
|
214
227
|
prevEnd--;
|
|
215
228
|
nextEnd--;
|
|
216
229
|
}
|
|
217
230
|
// Step 3: Mount new nodes if prev list is exhausted
|
|
218
231
|
if (prevStart > prevEnd) {
|
|
219
|
-
const before = nextChildren[nextEnd + 1]
|
|
232
|
+
const before = findHostReferenceFromElement(nextChildren[nextEnd + 1]) || nextReference;
|
|
220
233
|
for (let i = nextStart; i <= nextEnd; i++) {
|
|
221
|
-
mount(nextChildren[i], parentReference, before,
|
|
234
|
+
mount(nextChildren[i], parentReference, before, context, hostNamespace);
|
|
222
235
|
}
|
|
223
236
|
// Step 4: Remove prev nodes if next list is exhausted
|
|
224
237
|
}
|
|
@@ -246,12 +259,12 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
246
259
|
const prevIndex = keyToPrevIndexMap.get(nextChild.key);
|
|
247
260
|
if (prevIndex != null) {
|
|
248
261
|
const prevElement = prevChildren[prevIndex];
|
|
249
|
-
patch(prevElement, nextChild, parentReference, null,
|
|
262
|
+
patch(prevElement, nextChild, parentReference, null, context, hostNamespace);
|
|
250
263
|
toMove[i - nextStart] = prevIndex;
|
|
251
264
|
usedIndices.add(prevIndex);
|
|
252
265
|
}
|
|
253
266
|
else {
|
|
254
|
-
mount(nextChild, parentReference, nextChildren[i + 1]
|
|
267
|
+
mount(nextChild, parentReference, findHostReferenceFromElement(nextChildren[i + 1]) || nextReference, context, hostNamespace);
|
|
255
268
|
toMove[i - nextStart] = -1;
|
|
256
269
|
}
|
|
257
270
|
}
|
|
@@ -264,7 +277,7 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
264
277
|
// Insert in correct order
|
|
265
278
|
for (let i = nextEnd; i >= nextStart; i--) {
|
|
266
279
|
const currentChild = nextChildren[i];
|
|
267
|
-
const reference = nextChildren[i + 1]
|
|
280
|
+
const reference = findHostReferenceFromElement(nextChildren[i + 1]) || nextReference;
|
|
268
281
|
if (toMove[i - nextStart] !== -1) {
|
|
269
282
|
hostAdapter.insertBefore(parentReference, currentChild.reference, reference);
|
|
270
283
|
}
|
package/core/ref.d.ts
CHANGED
|
@@ -5,13 +5,13 @@ interface RefSimpElement extends SimpElement {
|
|
|
5
5
|
cleanup?: () => void;
|
|
6
6
|
};
|
|
7
7
|
}
|
|
8
|
-
export
|
|
8
|
+
export type RefObject<T> = {
|
|
9
9
|
current: T;
|
|
10
|
-
}
|
|
10
|
+
};
|
|
11
11
|
export type RefCallback<T> = {
|
|
12
|
-
bivarianceHack(instance: T
|
|
12
|
+
bivarianceHack(instance: T): (() => void | undefined) | void;
|
|
13
13
|
}['bivarianceHack'];
|
|
14
|
-
export type Ref<T> = RefCallback<T> | RefObject<T> | null;
|
|
14
|
+
export type Ref<T> = RefCallback<T> | RefObject<T | null> | null;
|
|
15
15
|
export declare function unmountRef(element: RefSimpElement): void;
|
|
16
16
|
export declare function applyRef(element: RefSimpElement): void;
|
|
17
17
|
export {};
|
package/core/rerender.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type { SimpElement } from './createElement.js';
|
|
1
|
+
import type { SimpElement, SimpElementStore } from './createElement.js';
|
|
2
2
|
export declare function rerender(element: SimpElement): void;
|
|
3
3
|
interface IRendererLocker {
|
|
4
4
|
_isLocked: boolean;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
_elementStores: Set<SimpElementStore>;
|
|
6
|
+
_last: SimpElementStore | undefined;
|
|
7
|
+
_track(element: SimpElementStore): void;
|
|
8
|
+
_untrack(element: SimpElementStore): void;
|
|
7
9
|
lock(): void;
|
|
8
|
-
track(element: SimpElement): void;
|
|
9
10
|
flush(): void;
|
|
10
11
|
}
|
|
11
|
-
export declare const
|
|
12
|
-
export declare const
|
|
12
|
+
export declare const batchingRerenderLocker: IRendererLocker;
|
|
13
|
+
export declare const renderingRerenderLocker: IRendererLocker;
|
|
13
14
|
export {};
|