@simpreact/simpreact 0.0.0-alpha.1f6ee65 → 0.0.1
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/core/createElement.d.ts +22 -15
- package/core/createElement.js +67 -23
- package/core/hostAdapter.d.ts +17 -7
- package/core/hostAdapter.js +4 -1
- package/core/index.d.ts +68 -3
- package/core/index.js +6 -3
- package/core/internal.d.ts +6 -3
- package/core/internal.js +6 -3
- package/core/lifecycleEventBus.d.ts +26 -0
- package/core/lifecycleEventBus.js +2 -0
- package/core/mounting.d.ts +9 -8
- package/core/mounting.js +87 -50
- package/core/patching.d.ts +6 -4
- package/core/patching.js +150 -162
- package/core/portal.d.ts +2 -0
- package/core/portal.js +9 -0
- package/core/ref.d.ts +17 -0
- package/core/ref.js +27 -0
- package/core/rerender.d.ts +11 -0
- package/core/rerender.js +61 -3
- package/core/unmounting.d.ts +2 -4
- package/core/unmounting.js +26 -27
- package/dom/attach-element-to-dom.d.ts +4 -0
- package/dom/attach-element-to-dom.js +9 -0
- package/dom/domAdapter.d.ts +3 -2
- package/dom/domAdapter.js +37 -113
- package/dom/events.d.ts +19 -0
- package/dom/events.js +129 -0
- package/dom/index.d.ts +1733 -1
- package/dom/index.js +2 -0
- package/dom/namespace.d.ts +2 -0
- package/dom/namespace.js +1 -0
- package/dom/props/controlled/index.d.ts +7 -0
- package/dom/props/controlled/index.js +51 -0
- package/dom/props/controlled/input.d.ts +7 -0
- package/dom/props/controlled/input.js +80 -0
- package/dom/props/controlled/select.d.ts +6 -0
- package/dom/props/controlled/select.js +76 -0
- package/dom/props/controlled/textarea.d.ts +6 -0
- package/dom/props/controlled/textarea.js +61 -0
- package/dom/props/dangerInnerHTML.d.ts +7 -0
- package/dom/props/dangerInnerHTML.js +24 -0
- package/dom/props/index.d.ts +1 -0
- package/dom/props/index.js +1 -0
- package/dom/props/props.d.ts +5 -0
- package/dom/props/props.js +197 -0
- package/dom/props/style.d.ts +1 -0
- package/dom/props/style.js +32 -0
- package/dom/render.d.ts +2 -2
- package/dom/render.js +31 -19
- package/hooks/index.d.ts +23 -12
- package/hooks/index.js +123 -29
- package/jsx-runtime/index.d.ts +247 -4
- package/jsx-runtime/index.js +2 -5
- package/package.json +22 -15
- package/shared/index.d.ts +19 -4
- package/shared/index.js +5 -4
- package/shared/lang.d.ts +3 -3
- package/shared/lang.js +3 -3
- package/shared/utils.d.ts +3 -2
- package/shared/utils.js +3 -6
- package/core/global.d.ts +0 -21
- package/core/global.js +0 -5
- package/shared/types.d.ts +0 -8
- package/shared/types.js +0 -1
package/core/patching.js
CHANGED
|
@@ -1,208 +1,171 @@
|
|
|
1
|
+
import { emptyMap, emptyObject } from '../shared';
|
|
1
2
|
import { normalizeRoot } from './createElement';
|
|
2
|
-
import {
|
|
3
|
-
import { clearElementHostReference, remove,
|
|
3
|
+
import { hostAdapter } from './hostAdapter';
|
|
4
|
+
import { clearElementHostReference, remove, unmount } from './unmounting';
|
|
4
5
|
import { mount, mountArrayChildren } from './mounting';
|
|
5
|
-
import {
|
|
6
|
-
|
|
6
|
+
import { applyRef } from './ref';
|
|
7
|
+
import { lifecycleEventBus } from './lifecycleEventBus';
|
|
8
|
+
export function patch(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace) {
|
|
7
9
|
if (prevElement.type !== nextElement.type || prevElement.key !== nextElement.key) {
|
|
8
|
-
replaceWithNewElement(prevElement, nextElement, parentReference, contextMap);
|
|
10
|
+
replaceWithNewElement(prevElement, nextElement, parentReference, contextMap, hostNamespace);
|
|
9
11
|
}
|
|
10
12
|
else if (nextElement.flag === 'HOST') {
|
|
11
|
-
|
|
13
|
+
patchHostElement(prevElement, nextElement, contextMap, hostNamespace);
|
|
12
14
|
}
|
|
13
15
|
else if (nextElement.flag === 'FC') {
|
|
14
|
-
|
|
15
|
-
nextElement.store = prevElement.store;
|
|
16
|
-
}
|
|
17
|
-
patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, contextMap);
|
|
16
|
+
patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace);
|
|
18
17
|
}
|
|
19
18
|
else if (nextElement.flag === 'TEXT') {
|
|
20
|
-
|
|
19
|
+
patchTextElement(prevElement, nextElement);
|
|
21
20
|
}
|
|
22
21
|
else if (nextElement.flag === 'FRAGMENT') {
|
|
23
|
-
patchFragment(prevElement, nextElement, parentReference,
|
|
22
|
+
patchFragment(prevElement, nextElement, parentReference, contextMap, hostNamespace);
|
|
24
23
|
}
|
|
25
24
|
else if (nextElement.flag === 'PROVIDER') {
|
|
26
|
-
patchProvider(prevElement, nextElement, parentReference,
|
|
25
|
+
patchProvider(prevElement, nextElement, parentReference, contextMap, hostNamespace);
|
|
26
|
+
}
|
|
27
|
+
else if (nextElement.flag === 'PORTAL') {
|
|
28
|
+
patchPortal(prevElement, nextElement, contextMap);
|
|
27
29
|
}
|
|
28
30
|
else {
|
|
29
|
-
patchConsumer(prevElement, nextElement, parentReference, nextReference, contextMap);
|
|
31
|
+
patchConsumer(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace);
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
|
-
function replaceWithNewElement(prevElement, nextElement, parentReference, contextMap) {
|
|
34
|
+
function replaceWithNewElement(prevElement, nextElement, parentReference, contextMap, hostNamespace) {
|
|
33
35
|
unmount(prevElement);
|
|
36
|
+
nextElement.parent = prevElement.parent;
|
|
34
37
|
if (nextElement.flag === 'HOST' && prevElement.flag === 'HOST') {
|
|
35
|
-
mount(nextElement, null, null, contextMap);
|
|
36
|
-
|
|
38
|
+
mount(nextElement, null, null, contextMap, hostNamespace);
|
|
39
|
+
hostAdapter.replaceChild(parentReference, nextElement.reference, prevElement.reference);
|
|
37
40
|
}
|
|
38
41
|
else {
|
|
39
|
-
mount(nextElement, parentReference, findHostReferenceFromElement(prevElement), contextMap);
|
|
42
|
+
mount(nextElement, parentReference, findHostReferenceFromElement(prevElement), contextMap, hostNamespace);
|
|
40
43
|
clearElementHostReference(prevElement, parentReference);
|
|
41
44
|
}
|
|
42
45
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
while (temp != null) {
|
|
47
|
-
flag = temp.flag;
|
|
48
|
-
if (flag === 'HOST' || flag === 'TEXT') {
|
|
49
|
-
return temp.reference;
|
|
50
|
-
}
|
|
51
|
-
temp = (Array.isArray(temp.children) ? temp.children[0] : temp.children);
|
|
46
|
+
function patchHostElement(prevElement, nextElement, contextMap, hostNamespace) {
|
|
47
|
+
if (prevElement.ref) {
|
|
48
|
+
nextElement.ref = prevElement.ref;
|
|
52
49
|
}
|
|
53
|
-
|
|
50
|
+
const hostNamespaces = hostAdapter.getHostNamespaces(nextElement, hostNamespace);
|
|
51
|
+
hostNamespace = hostNamespaces?.self;
|
|
52
|
+
nextElement.reference = prevElement.reference;
|
|
53
|
+
hostAdapter.attachElementToReference(nextElement, nextElement.reference);
|
|
54
|
+
patchChildren(prevElement.children, nextElement.children, nextElement.reference, null, nextElement, contextMap, hostNamespaces?.children);
|
|
55
|
+
hostAdapter.patchProps(nextElement.reference, prevElement, nextElement, hostNamespace);
|
|
56
|
+
if (prevElement.className !== nextElement.className) {
|
|
57
|
+
hostAdapter.setClassname(nextElement.reference, nextElement.className, hostNamespace);
|
|
58
|
+
}
|
|
59
|
+
applyRef(nextElement);
|
|
54
60
|
}
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
for (const propName in nextProps) {
|
|
60
|
-
const prevValue = prevProps[propName];
|
|
61
|
-
const nextValue = nextProps[propName];
|
|
62
|
-
if (prevValue !== nextValue) {
|
|
63
|
-
GLOBAL.hostAdapter.patchProp(hostReference, propName, prevValue, nextValue);
|
|
64
|
-
}
|
|
61
|
+
function patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace) {
|
|
62
|
+
(nextElement.store = prevElement.store ||= {}).latestElement = nextElement;
|
|
63
|
+
if (hostNamespace) {
|
|
64
|
+
nextElement.store.hostNamespace = hostNamespace;
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
GLOBAL.hostAdapter.patchProp(hostReference, propName, prevProps[propName], null);
|
|
69
|
-
}
|
|
66
|
+
if (contextMap) {
|
|
67
|
+
nextElement.contextMap = contextMap;
|
|
70
68
|
}
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
let nextChildren;
|
|
70
|
+
try {
|
|
71
|
+
lifecycleEventBus.publish({ type: 'beforeRender', element: nextElement, phase: 'updating' });
|
|
72
|
+
nextChildren = normalizeRoot(nextElement.type(nextElement.props || emptyObject), false);
|
|
73
|
+
lifecycleEventBus.publish({ type: 'afterRender', phase: 'updating' });
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
lifecycleEventBus.publish({ type: 'errored', element: nextElement, error, phase: 'updating' });
|
|
77
|
+
return;
|
|
73
78
|
}
|
|
74
|
-
|
|
79
|
+
const prevChildren = prevElement.children;
|
|
80
|
+
if (nextChildren) {
|
|
81
|
+
nextElement.children = nextChildren;
|
|
82
|
+
}
|
|
83
|
+
patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, contextMap, hostNamespace);
|
|
84
|
+
lifecycleEventBus.publish({ type: 'updated', element: nextElement });
|
|
75
85
|
}
|
|
76
|
-
function
|
|
86
|
+
function patchTextElement(prevElement, nextElement) {
|
|
87
|
+
nextElement.reference = prevElement.reference;
|
|
88
|
+
if (nextElement.children !== prevElement.children) {
|
|
89
|
+
hostAdapter.setTextContent(nextElement.reference, nextElement.children);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function patchFragment(prevElement, nextElement, parentReference, contextMap, hostNamespace) {
|
|
93
|
+
let nextReference = null;
|
|
94
|
+
if (Array.isArray(prevElement.children) && !Array.isArray(nextElement.children) && nextElement.children) {
|
|
95
|
+
nextReference = hostAdapter.findNextSiblingReference(findHostReferenceFromElement(prevElement.children[prevElement.children.length - 1]));
|
|
96
|
+
}
|
|
97
|
+
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, contextMap, hostNamespace);
|
|
98
|
+
}
|
|
99
|
+
function patchProvider(prevElement, nextElement, parentReference, contextMap, hostNamespace) {
|
|
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) {
|
|
116
|
+
const prevContainer = prevElement.ref;
|
|
117
|
+
const nextContainer = nextElement.ref;
|
|
118
|
+
const nextChildren = nextElement.children;
|
|
119
|
+
patchChildren(prevElement.children, nextChildren, prevContainer, null, nextElement, contextMap, hostAdapter.getHostNamespaces(nextChildren, undefined)?.self);
|
|
120
|
+
nextElement.reference = prevElement.reference;
|
|
121
|
+
if (prevContainer !== nextContainer && nextChildren != null) {
|
|
122
|
+
hostAdapter.removeChild(prevContainer, nextChildren.reference);
|
|
123
|
+
hostAdapter.appendChild(nextContainer, nextChildren.reference);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export function updateFunctionalComponent(element, parentReference, nextReference, contextMap, hostNamespace) {
|
|
127
|
+
patchFunctionalComponent(element, element, parentReference, nextReference, contextMap, hostNamespace);
|
|
128
|
+
}
|
|
129
|
+
function patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, contextMap, hostNamespace) {
|
|
77
130
|
if (Array.isArray(prevChildren)) {
|
|
78
131
|
if (Array.isArray(nextChildren)) {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
if (prevChildrenLength === 0) {
|
|
82
|
-
if (nextChildrenLength > 0) {
|
|
83
|
-
mountArrayChildren(nextChildren, parentReference, nextReference, contextMap);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
else if (nextChildrenLength === 0) {
|
|
87
|
-
removeAllChildren(parentReference, parentElement, prevChildren);
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, contextMap);
|
|
132
|
+
for (const child of nextChildren) {
|
|
133
|
+
child.parent = nextElement;
|
|
91
134
|
}
|
|
135
|
+
patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, contextMap, hostNamespace);
|
|
92
136
|
}
|
|
93
|
-
else if (
|
|
94
|
-
|
|
95
|
-
GLOBAL.hostAdapter.setTextContent(parentReference, (nextChildren || ''));
|
|
137
|
+
else if (nextChildren) {
|
|
138
|
+
patchKeyedChildren(prevChildren, [nextChildren], parentReference, nextReference, contextMap, hostNamespace);
|
|
96
139
|
}
|
|
97
140
|
else {
|
|
98
|
-
|
|
99
|
-
|
|
141
|
+
unmount(prevChildren);
|
|
142
|
+
hostAdapter.clearNode(parentReference);
|
|
100
143
|
}
|
|
101
144
|
}
|
|
102
|
-
else if (
|
|
145
|
+
else if (prevChildren) {
|
|
103
146
|
if (Array.isArray(nextChildren)) {
|
|
104
|
-
|
|
105
|
-
mountArrayChildren(nextChildren, parentReference, nextReference, contextMap);
|
|
147
|
+
patchKeyedChildren([prevChildren], nextChildren, parentReference, nextReference, contextMap, hostNamespace);
|
|
106
148
|
}
|
|
107
|
-
else if (
|
|
108
|
-
|
|
149
|
+
else if (nextChildren) {
|
|
150
|
+
nextChildren.parent = nextElement;
|
|
151
|
+
patch(prevChildren, nextChildren, parentReference, nextReference, contextMap, hostNamespace);
|
|
109
152
|
}
|
|
110
153
|
else {
|
|
111
|
-
|
|
112
|
-
|
|
154
|
+
unmount(prevChildren);
|
|
155
|
+
hostAdapter.clearNode(parentReference);
|
|
113
156
|
}
|
|
114
157
|
}
|
|
115
158
|
else {
|
|
116
159
|
if (Array.isArray(nextChildren)) {
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
else if (isPrimitive(nextChildren)) {
|
|
120
|
-
unmount(prevChildren);
|
|
121
|
-
GLOBAL.hostAdapter.setTextContent(parentReference, nextChildren);
|
|
160
|
+
mountArrayChildren(nextChildren, parentReference, nextReference, contextMap, nextElement, hostNamespace);
|
|
122
161
|
}
|
|
123
|
-
else {
|
|
124
|
-
|
|
162
|
+
else if (nextChildren) {
|
|
163
|
+
nextChildren.parent = nextElement;
|
|
164
|
+
mount(nextChildren, parentReference, nextReference, contextMap, hostNamespace);
|
|
125
165
|
}
|
|
126
166
|
}
|
|
127
167
|
}
|
|
128
|
-
function
|
|
129
|
-
unmount(prevChildren);
|
|
130
|
-
mountArrayChildren(nextChildren, parentReference, findHostReferenceFromElement(prevChildren), contextMap);
|
|
131
|
-
clearElementHostReference(prevChildren, parentReference);
|
|
132
|
-
}
|
|
133
|
-
function patchSingleTextChild(prevChildren, nextChildren, parentReference) {
|
|
134
|
-
if (prevChildren !== nextChildren) {
|
|
135
|
-
GLOBAL.hostAdapter.setTextContent(parentReference, nextChildren);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
// export function patchNonKeyedChildren(
|
|
139
|
-
// prevChildren: SimpElement[],
|
|
140
|
-
// nextChildren: SimpElement[],
|
|
141
|
-
// parentReference: HostReference,
|
|
142
|
-
// prevChildrenLength: number,
|
|
143
|
-
// nextChildrenLength: number,
|
|
144
|
-
// nextReference: Nullable<HostReference>
|
|
145
|
-
// ): void {
|
|
146
|
-
// const commonLength = prevChildrenLength > nextChildrenLength ? nextChildrenLength : prevChildrenLength;
|
|
147
|
-
// let i = 0;
|
|
148
|
-
// let prevChild;
|
|
149
|
-
// let nextChild;
|
|
150
|
-
//
|
|
151
|
-
// for (; i < commonLength; ++i) {
|
|
152
|
-
// nextChild = nextChildren[i];
|
|
153
|
-
// prevChild = prevChildren[i];
|
|
154
|
-
//
|
|
155
|
-
// patch(prevChild as SimpElement, nextChild as SimpElement, parentReference, nextReference);
|
|
156
|
-
// prevChildren[i] = nextChild!;
|
|
157
|
-
// }
|
|
158
|
-
// if (prevChildrenLength < nextChildrenLength) {
|
|
159
|
-
// for (i = commonLength; i < nextChildrenLength; ++i) {
|
|
160
|
-
// nextChild = nextChildren[i];
|
|
161
|
-
// mount(nextChild as SimpElement, parentReference, nextReference);
|
|
162
|
-
// }
|
|
163
|
-
// } else if (prevChildrenLength > nextChildrenLength) {
|
|
164
|
-
// for (i = commonLength; i < prevChildrenLength; ++i) {
|
|
165
|
-
// remove(prevChildren[i] as SimpElement, parentReference);
|
|
166
|
-
// }
|
|
167
|
-
// }
|
|
168
|
-
// }
|
|
169
|
-
function patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, contextMap) {
|
|
170
|
-
nextElement.contextMap = contextMap;
|
|
171
|
-
GLOBAL.eventBus.publish({ type: 'beforeRender', element: nextElement });
|
|
172
|
-
const nextChildren = normalizeRoot(nextElement.type(nextElement.props || EMPTY_OBJECT));
|
|
173
|
-
GLOBAL.eventBus.publish({ type: 'afterRender' });
|
|
174
|
-
if (nextChildren != null) {
|
|
175
|
-
nextElement.children = nextChildren;
|
|
176
|
-
}
|
|
177
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, prevElement, contextMap);
|
|
178
|
-
GLOBAL.eventBus.publish({ type: 'mounted', element: nextElement });
|
|
179
|
-
}
|
|
180
|
-
function patchText(prevElement, nextElement) {
|
|
181
|
-
const nextText = nextElement.children;
|
|
182
|
-
const reference = (nextElement.reference = prevElement.reference);
|
|
183
|
-
if (nextText !== prevElement.children) {
|
|
184
|
-
GLOBAL.hostAdapter.setTextContent(reference, nextText);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
function patchFragment(prevElement, nextElement, parentReference, nextReference, contextMap) {
|
|
188
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, prevElement, contextMap);
|
|
189
|
-
}
|
|
190
|
-
function patchProvider(prevElement, nextElement, parentReference, nextReference, contextMap) {
|
|
191
|
-
contextMap = new Map(contextMap);
|
|
192
|
-
contextMap.set(nextElement.type.context, nextElement.props.value);
|
|
193
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, prevElement, contextMap);
|
|
194
|
-
}
|
|
195
|
-
function patchConsumer(prevElement, nextElement, parentReference, nextReference, contextMap) {
|
|
196
|
-
const children = normalizeRoot(nextElement.type(nextElement.props || EMPTY_OBJECT, contextMap || EMPTY_MAP));
|
|
197
|
-
if (children != null) {
|
|
198
|
-
nextElement.children = children;
|
|
199
|
-
}
|
|
200
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, prevElement, contextMap);
|
|
201
|
-
}
|
|
202
|
-
export function updateFunctionalComponent(element, parentReference, nextReference, contextMap) {
|
|
203
|
-
patch(element, element, parentReference, nextReference, contextMap);
|
|
204
|
-
}
|
|
205
|
-
export function patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, contextMap) {
|
|
168
|
+
export function patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, contextMap, hostNamespace) {
|
|
206
169
|
let prevStart = 0;
|
|
207
170
|
let nextStart = 0;
|
|
208
171
|
let prevEnd = prevChildren.length - 1;
|
|
@@ -211,13 +174,13 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
211
174
|
while (prevStart <= prevEnd &&
|
|
212
175
|
nextStart <= nextEnd &&
|
|
213
176
|
prevChildren[prevStart].key === nextChildren[nextStart].key) {
|
|
214
|
-
patch(prevChildren[prevStart], nextChildren[nextStart], parentReference, null, contextMap);
|
|
177
|
+
patch(prevChildren[prevStart], nextChildren[nextStart], parentReference, null, contextMap, hostNamespace);
|
|
215
178
|
prevStart++;
|
|
216
179
|
nextStart++;
|
|
217
180
|
}
|
|
218
181
|
// Step 2: Sync from end
|
|
219
182
|
while (prevStart <= prevEnd && nextStart <= nextEnd && prevChildren[prevEnd].key === nextChildren[nextEnd].key) {
|
|
220
|
-
patch(prevChildren[prevEnd], nextChildren[nextEnd], parentReference, null, contextMap);
|
|
183
|
+
patch(prevChildren[prevEnd], nextChildren[nextEnd], parentReference, null, contextMap, hostNamespace);
|
|
221
184
|
prevEnd--;
|
|
222
185
|
nextEnd--;
|
|
223
186
|
}
|
|
@@ -225,7 +188,7 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
225
188
|
if (prevStart > prevEnd) {
|
|
226
189
|
const before = nextChildren[nextEnd + 1]?.reference || nextReference;
|
|
227
190
|
for (let i = nextStart; i <= nextEnd; i++) {
|
|
228
|
-
mount(nextChildren[i], parentReference, before, contextMap);
|
|
191
|
+
mount(nextChildren[i], parentReference, before, contextMap, hostNamespace);
|
|
229
192
|
}
|
|
230
193
|
// Step 4: Remove prev nodes if next list is exhausted
|
|
231
194
|
}
|
|
@@ -240,8 +203,9 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
240
203
|
const keyToPrevIndexMap = new Map();
|
|
241
204
|
for (let i = prevStart; i <= prevEnd; i++) {
|
|
242
205
|
const key = prevChildren[i].key;
|
|
243
|
-
if (key != null)
|
|
206
|
+
if (key != null) {
|
|
244
207
|
keyToPrevIndexMap.set(key, i);
|
|
208
|
+
}
|
|
245
209
|
}
|
|
246
210
|
// Track reused indices and move plan
|
|
247
211
|
const toMove = new Array(nextEnd - nextStart + 1);
|
|
@@ -252,12 +216,12 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
252
216
|
const prevIndex = keyToPrevIndexMap.get(nextChild.key);
|
|
253
217
|
if (prevIndex != null) {
|
|
254
218
|
const prevElement = prevChildren[prevIndex];
|
|
255
|
-
patch(prevElement, nextChild, parentReference, null, contextMap);
|
|
219
|
+
patch(prevElement, nextChild, parentReference, null, contextMap, hostNamespace);
|
|
256
220
|
toMove[i - nextStart] = prevIndex;
|
|
257
221
|
usedIndices.add(prevIndex);
|
|
258
222
|
}
|
|
259
223
|
else {
|
|
260
|
-
mount(nextChild, parentReference, nextChildren[i + 1]?.reference || nextReference, contextMap);
|
|
224
|
+
mount(nextChild, parentReference, nextChildren[i + 1]?.reference || nextReference, contextMap, hostNamespace);
|
|
261
225
|
toMove[i - nextStart] = -1;
|
|
262
226
|
}
|
|
263
227
|
}
|
|
@@ -272,8 +236,32 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
272
236
|
const currentChild = nextChildren[i];
|
|
273
237
|
const reference = nextChildren[i + 1]?.reference || nextReference;
|
|
274
238
|
if (toMove[i - nextStart] !== -1) {
|
|
275
|
-
|
|
239
|
+
hostAdapter.insertBefore(parentReference, currentChild.reference, reference);
|
|
276
240
|
}
|
|
277
241
|
}
|
|
278
242
|
}
|
|
279
243
|
}
|
|
244
|
+
export function findParentReferenceFromElement(element) {
|
|
245
|
+
let flag;
|
|
246
|
+
let temp = element;
|
|
247
|
+
while (temp != null) {
|
|
248
|
+
flag = temp.flag;
|
|
249
|
+
if (flag === 'HOST') {
|
|
250
|
+
return temp.reference;
|
|
251
|
+
}
|
|
252
|
+
temp = temp.parent;
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
export function findHostReferenceFromElement(element) {
|
|
257
|
+
let flag;
|
|
258
|
+
let temp = element;
|
|
259
|
+
while (temp != null) {
|
|
260
|
+
flag = temp.flag;
|
|
261
|
+
if (flag === 'HOST' || flag === 'TEXT' || flag === 'PORTAL') {
|
|
262
|
+
return temp.reference;
|
|
263
|
+
}
|
|
264
|
+
temp = (Array.isArray(temp.children) ? temp.children[0] : temp.children);
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
}
|
package/core/portal.d.ts
ADDED
package/core/portal.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { normalizeRoot } from './createElement';
|
|
2
|
+
export function createPortal(children, container) {
|
|
3
|
+
const element = { flag: 'PORTAL', parent: null };
|
|
4
|
+
if ((children = normalizeRoot(children, false))) {
|
|
5
|
+
element.children = children;
|
|
6
|
+
}
|
|
7
|
+
element.ref = container;
|
|
8
|
+
return element;
|
|
9
|
+
}
|
package/core/ref.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SimpElement } from './createElement';
|
|
2
|
+
interface RefSimpElement extends SimpElement {
|
|
3
|
+
ref?: {
|
|
4
|
+
value: NonNullable<Ref<unknown>>;
|
|
5
|
+
cleanup?: () => void;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export interface RefObject<T> {
|
|
9
|
+
current: T;
|
|
10
|
+
}
|
|
11
|
+
export type RefCallback<T> = {
|
|
12
|
+
bivarianceHack(instance: T | null): (() => void) | void;
|
|
13
|
+
}['bivarianceHack'];
|
|
14
|
+
export type Ref<T> = RefCallback<T> | RefObject<T> | null;
|
|
15
|
+
export declare function unmountRef(element: RefSimpElement): void;
|
|
16
|
+
export declare function applyRef(element: RefSimpElement): void;
|
|
17
|
+
export {};
|
package/core/ref.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function unmountRef(element) {
|
|
2
|
+
if (element.ref == null) {
|
|
3
|
+
return;
|
|
4
|
+
}
|
|
5
|
+
if (typeof element.ref.cleanup === 'function') {
|
|
6
|
+
element.ref.cleanup();
|
|
7
|
+
}
|
|
8
|
+
if (typeof element.ref.value !== 'function') {
|
|
9
|
+
element.ref.value.current = null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function applyRef(element) {
|
|
13
|
+
if (element.ref == null) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (typeof element.ref.cleanup === 'function') {
|
|
17
|
+
element.ref.cleanup();
|
|
18
|
+
}
|
|
19
|
+
if (typeof element.ref.value === 'function') {
|
|
20
|
+
let cleanup;
|
|
21
|
+
if ((cleanup = element.ref.value(element.reference))) {
|
|
22
|
+
element.ref.cleanup = cleanup;
|
|
23
|
+
}
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
element.ref.value.current = element.reference;
|
|
27
|
+
}
|
package/core/rerender.d.ts
CHANGED
|
@@ -1,2 +1,13 @@
|
|
|
1
1
|
import type { SimpElement } from './createElement';
|
|
2
2
|
export declare function rerender(element: SimpElement): void;
|
|
3
|
+
interface IRendererLocker {
|
|
4
|
+
_isLocked: boolean;
|
|
5
|
+
_elements: Set<SimpElement>;
|
|
6
|
+
isLocked: boolean;
|
|
7
|
+
lock(): void;
|
|
8
|
+
track(element: SimpElement): void;
|
|
9
|
+
flush(): void;
|
|
10
|
+
}
|
|
11
|
+
export declare const syncRerenderLocker: IRendererLocker;
|
|
12
|
+
export declare const asyncRerenderLocker: IRendererLocker;
|
|
13
|
+
export {};
|
package/core/rerender.js
CHANGED
|
@@ -1,5 +1,63 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { GLOBAL } from './global';
|
|
1
|
+
import { findParentReferenceFromElement, updateFunctionalComponent } from './patching';
|
|
3
2
|
export function rerender(element) {
|
|
4
|
-
|
|
3
|
+
if (element.flag !== 'FC') {
|
|
4
|
+
throw new TypeError('Re-rendering is only supported for FC elements.');
|
|
5
|
+
}
|
|
6
|
+
if (element.unmounted) {
|
|
7
|
+
console.warn('The component unmounted.');
|
|
8
|
+
}
|
|
9
|
+
if (syncRerenderLocker.isLocked) {
|
|
10
|
+
syncRerenderLocker.track(element);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
else if (asyncRerenderLocker.isLocked) {
|
|
14
|
+
asyncRerenderLocker.track(element);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
asyncRerenderLocker.lock();
|
|
18
|
+
updateFunctionalComponent(element, findParentReferenceFromElement(element), null, element.contextMap || null, element.store.hostNamespace);
|
|
19
|
+
asyncRerenderLocker.flush();
|
|
20
|
+
}
|
|
5
21
|
}
|
|
22
|
+
export const syncRerenderLocker = {
|
|
23
|
+
_isLocked: false,
|
|
24
|
+
_elements: new Set(),
|
|
25
|
+
get isLocked() {
|
|
26
|
+
return this._isLocked;
|
|
27
|
+
},
|
|
28
|
+
lock() {
|
|
29
|
+
this._isLocked = true;
|
|
30
|
+
},
|
|
31
|
+
track(element) {
|
|
32
|
+
this._elements.add(element);
|
|
33
|
+
},
|
|
34
|
+
flush() {
|
|
35
|
+
this._isLocked = false;
|
|
36
|
+
for (const element of this._elements) {
|
|
37
|
+
this._elements.delete(element);
|
|
38
|
+
rerender(element.store.latestElement);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
export const asyncRerenderLocker = {
|
|
43
|
+
_isLocked: false,
|
|
44
|
+
_elements: new Set(),
|
|
45
|
+
get isLocked() {
|
|
46
|
+
return this._isLocked;
|
|
47
|
+
},
|
|
48
|
+
lock() {
|
|
49
|
+
this._isLocked = true;
|
|
50
|
+
},
|
|
51
|
+
track(element) {
|
|
52
|
+
this._elements.add(element);
|
|
53
|
+
},
|
|
54
|
+
flush() {
|
|
55
|
+
this._isLocked = false;
|
|
56
|
+
queueMicrotask(() => {
|
|
57
|
+
for (const element of this._elements) {
|
|
58
|
+
this._elements.delete(element);
|
|
59
|
+
rerender(element.store.latestElement);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
};
|
package/core/unmounting.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
+
import type { Many, Maybe } from '../shared';
|
|
1
2
|
import type { SimpElement } from './createElement';
|
|
2
|
-
import type { Maybe } from '../shared';
|
|
3
3
|
import type { HostReference } from './hostAdapter';
|
|
4
|
-
export declare function unmount(element: SimpElement): void;
|
|
5
|
-
export declare function unmountAllChildren(children: SimpElement[]): void;
|
|
4
|
+
export declare function unmount(element: Many<SimpElement>): void;
|
|
6
5
|
export declare function clearElementHostReference(element: Maybe<SimpElement>, parentHostReference: HostReference): void;
|
|
7
|
-
export declare function removeAllChildren(hostReference: HostReference, element: SimpElement, children: SimpElement[]): void;
|
|
8
6
|
export declare function remove(element: SimpElement, parentReference: HostReference): void;
|
package/core/unmounting.js
CHANGED
|
@@ -1,32 +1,43 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hostAdapter } from './hostAdapter';
|
|
2
|
+
import { unmountRef } from './ref';
|
|
3
|
+
import { lifecycleEventBus } from './lifecycleEventBus';
|
|
2
4
|
export function unmount(element) {
|
|
5
|
+
if (Array.isArray(element)) {
|
|
6
|
+
for (const child of element) {
|
|
7
|
+
unmount(child);
|
|
8
|
+
}
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
3
11
|
if (element.flag === 'FC') {
|
|
4
|
-
// FC element always has
|
|
5
|
-
|
|
6
|
-
|
|
12
|
+
// FC element always has Maybe<SimpElement> due to normalization.
|
|
13
|
+
if (element.children) {
|
|
14
|
+
unmount(element.children);
|
|
15
|
+
}
|
|
16
|
+
element.unmounted = true;
|
|
17
|
+
lifecycleEventBus.publish({ type: 'unmounted', element });
|
|
7
18
|
return;
|
|
8
19
|
}
|
|
9
20
|
if (element.flag === 'TEXT') {
|
|
10
21
|
return;
|
|
11
22
|
}
|
|
23
|
+
if (element.flag === 'PORTAL') {
|
|
24
|
+
remove(element.children, element.ref);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
12
27
|
// Only FRAGMENT, PROVIDER, CONSUMER, and HOST elements remain,
|
|
13
28
|
// with Maybe<Many<SimpElement>> children due to normalization.
|
|
14
|
-
if (
|
|
15
|
-
unmountAllChildren(element.children);
|
|
16
|
-
}
|
|
17
|
-
else if (element.children != null) {
|
|
29
|
+
if (element.children) {
|
|
18
30
|
unmount(element.children);
|
|
19
31
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
unmount(child);
|
|
32
|
+
if (element.flag === 'HOST') {
|
|
33
|
+
unmountRef(element);
|
|
34
|
+
hostAdapter.unmountProps(element.reference, element);
|
|
24
35
|
}
|
|
25
36
|
}
|
|
26
37
|
export function clearElementHostReference(element, parentHostReference) {
|
|
27
38
|
while (element != null) {
|
|
28
|
-
if (element.flag === 'HOST' || element.flag === 'TEXT') {
|
|
29
|
-
|
|
39
|
+
if (element.flag === 'HOST' || element.flag === 'TEXT' || element.flag === 'PORTAL') {
|
|
40
|
+
hostAdapter.removeChild(parentHostReference, element.reference);
|
|
30
41
|
return;
|
|
31
42
|
}
|
|
32
43
|
const children = element.children;
|
|
@@ -41,24 +52,12 @@ export function clearElementHostReference(element, parentHostReference) {
|
|
|
41
52
|
}
|
|
42
53
|
return;
|
|
43
54
|
}
|
|
44
|
-
else if (children
|
|
55
|
+
else if (children) {
|
|
45
56
|
element = children;
|
|
46
57
|
}
|
|
47
58
|
}
|
|
48
59
|
}
|
|
49
60
|
}
|
|
50
|
-
export function removeAllChildren(hostReference, element, children) {
|
|
51
|
-
unmountAllChildren(children);
|
|
52
|
-
if (element.flag === 'FRAGMENT' ||
|
|
53
|
-
element.flag === 'FC' ||
|
|
54
|
-
element.flag === 'PROVIDER' ||
|
|
55
|
-
element.flag === 'CONSUMER') {
|
|
56
|
-
clearElementHostReference(element, hostReference);
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
GLOBAL.hostAdapter.clearNode(hostReference);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
61
|
export function remove(element, parentReference) {
|
|
63
62
|
unmount(element);
|
|
64
63
|
clearElementHostReference(element, parentReference);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Nullable } from '../shared';
|
|
2
|
+
import type { SimpElement } from '../core/internal.js';
|
|
3
|
+
export declare function attachElementToDom(element: SimpElement, dom: Node): void;
|
|
4
|
+
export declare function getElementFromDom(target: Nullable<EventTarget>): Nullable<SimpElement>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const elementPropertyName = '__SIMP_ELEMENT__';
|
|
2
|
+
export function attachElementToDom(element, dom) {
|
|
3
|
+
if (dom.nodeType !== Node.TEXT_NODE) {
|
|
4
|
+
Object.defineProperty(dom, elementPropertyName, { value: element, writable: true });
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export function getElementFromDom(target) {
|
|
8
|
+
return target?.[elementPropertyName] ?? null;
|
|
9
|
+
}
|