@simpreact/simpreact 0.0.3 → 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 +4 -7
- package/compat/core.js +2 -5
- package/compat/hooks.d.ts +0 -2
- package/compat/hooks.js +0 -2
- package/compat/index.d.ts +5 -4
- package/compat/index.js +3 -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 +1 -24
- package/core/index.d.ts +2 -21
- package/core/index.js +3 -3
- package/core/internal.d.ts +1 -1
- package/core/internal.js +1 -1
- package/core/memo.d.ts +10 -0
- package/core/memo.js +11 -0
- package/core/mounting.d.ts +6 -9
- package/core/mounting.js +21 -53
- package/core/patching.d.ts +4 -5
- package/core/patching.js +55 -82
- package/core/rerender.d.ts +5 -4
- package/core/rerender.js +76 -24
- package/core/unmounting.js +3 -3
- package/dom/attach-element-to-dom.js +10 -1
- package/dom/events.d.ts +6 -1
- package/dom/events.js +12 -2
- package/hooks/index.d.ts +1 -3
- package/hooks/index.js +6 -7
- package/package.json +1 -1
- package/shared/index.d.ts +6 -0
- package/shared/index.js +12 -3
- package/shared/utils.d.ts +1 -0
- package/shared/utils.js +20 -0
- package/compat/utils.d.ts +0 -1
- package/compat/utils.js +0 -3
- package/core/context.d.ts +0 -18
- package/core/context.js +0 -18
package/core/patching.js
CHANGED
|
@@ -1,50 +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
|
-
|
|
9
|
+
import { isMemo } from './memo.js';
|
|
10
|
+
export function patch(prevElement, nextElement, parentReference, nextReference, context, hostNamespace) {
|
|
10
11
|
if (prevElement.type !== nextElement.type || prevElement.key !== nextElement.key) {
|
|
11
|
-
replaceWithNewElement(prevElement, nextElement, parentReference,
|
|
12
|
+
replaceWithNewElement(prevElement, nextElement, parentReference, context, hostNamespace);
|
|
12
13
|
}
|
|
13
14
|
else if (nextElement.flag === 'HOST') {
|
|
14
|
-
patchHostElement(prevElement, nextElement,
|
|
15
|
+
patchHostElement(prevElement, nextElement, context, hostNamespace);
|
|
15
16
|
}
|
|
16
17
|
else if (nextElement.flag === 'FC') {
|
|
17
|
-
patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference,
|
|
18
|
+
patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, context, hostNamespace);
|
|
18
19
|
}
|
|
19
20
|
else if (nextElement.flag === 'TEXT') {
|
|
20
21
|
patchTextElement(prevElement, nextElement);
|
|
21
22
|
}
|
|
22
23
|
else if (nextElement.flag === 'FRAGMENT') {
|
|
23
|
-
patchFragment(prevElement, nextElement, parentReference,
|
|
24
|
-
}
|
|
25
|
-
else if (nextElement.flag === 'PROVIDER') {
|
|
26
|
-
patchProvider(prevElement, nextElement, parentReference, contextMap, hostNamespace);
|
|
27
|
-
}
|
|
28
|
-
else if (nextElement.flag === 'PORTAL') {
|
|
29
|
-
patchPortal(prevElement, nextElement, contextMap);
|
|
24
|
+
patchFragment(prevElement, nextElement, parentReference, context, hostNamespace);
|
|
30
25
|
}
|
|
31
26
|
else {
|
|
32
|
-
|
|
27
|
+
patchPortal(prevElement, nextElement, context);
|
|
33
28
|
}
|
|
34
29
|
}
|
|
35
|
-
function replaceWithNewElement(prevElement, nextElement, parentReference,
|
|
30
|
+
function replaceWithNewElement(prevElement, nextElement, parentReference, context, hostNamespace) {
|
|
36
31
|
unmount(prevElement);
|
|
37
32
|
nextElement.parent = prevElement.parent;
|
|
38
33
|
if (nextElement.flag === 'HOST' && prevElement.flag === 'HOST') {
|
|
39
|
-
mount(nextElement, null, null,
|
|
34
|
+
mount(nextElement, null, null, context, hostNamespace);
|
|
40
35
|
hostAdapter.replaceChild(parentReference, nextElement.reference, prevElement.reference);
|
|
41
36
|
}
|
|
42
37
|
else {
|
|
43
|
-
mount(nextElement, parentReference, findHostReferenceFromElement(prevElement),
|
|
38
|
+
mount(nextElement, parentReference, findHostReferenceFromElement(prevElement), context, hostNamespace);
|
|
44
39
|
clearElementHostReference(prevElement, parentReference);
|
|
45
40
|
}
|
|
46
41
|
}
|
|
47
|
-
function patchHostElement(prevElement, nextElement,
|
|
42
|
+
function patchHostElement(prevElement, nextElement, context, hostNamespace) {
|
|
48
43
|
if (prevElement.ref) {
|
|
49
44
|
nextElement.ref = prevElement.ref;
|
|
50
45
|
}
|
|
@@ -52,25 +47,32 @@ function patchHostElement(prevElement, nextElement, contextMap, hostNamespace) {
|
|
|
52
47
|
hostNamespace = hostNamespaces?.self;
|
|
53
48
|
nextElement.reference = prevElement.reference;
|
|
54
49
|
hostAdapter.attachElementToReference(nextElement, nextElement.reference);
|
|
55
|
-
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);
|
|
56
51
|
hostAdapter.patchProps(nextElement.reference, prevElement, nextElement, hostNamespace);
|
|
57
52
|
if (prevElement.className !== nextElement.className) {
|
|
58
53
|
hostAdapter.setClassname(nextElement.reference, nextElement.className, hostNamespace);
|
|
59
54
|
}
|
|
60
55
|
applyRef(nextElement);
|
|
61
56
|
}
|
|
62
|
-
function patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
: prevElement.store;
|
|
66
|
-
prevStore.latestElement = nextElement;
|
|
67
|
-
nextElement.store = prevStore;
|
|
57
|
+
function patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, context, hostNamespace) {
|
|
58
|
+
nextElement.store = prevElement.store || {};
|
|
59
|
+
nextElement.store.latestElement = nextElement;
|
|
68
60
|
if (hostNamespace) {
|
|
69
61
|
nextElement.store.hostNamespace = hostNamespace;
|
|
70
62
|
}
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
let forceRender = false;
|
|
64
|
+
if (prevElement.store?.forceRender) {
|
|
65
|
+
forceRender = true;
|
|
66
|
+
prevElement.store.forceRender = false;
|
|
73
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;
|
|
74
76
|
// FC element always has Maybe<SimpElement> children due to normalization process.
|
|
75
77
|
let nextChildren;
|
|
76
78
|
let triedToRerenderUnsubscribe;
|
|
@@ -85,13 +87,7 @@ function patchFunctionalComponent(prevElement, nextElement, parentReference, nex
|
|
|
85
87
|
do {
|
|
86
88
|
triedToRerender = false;
|
|
87
89
|
if (++rerenderCounter >= 25) {
|
|
88
|
-
|
|
89
|
-
type: 'errored',
|
|
90
|
-
element: nextElement,
|
|
91
|
-
error: new Error('Too many re-renders. SimpReact limits the number of renders to prevent an infinite loop.'),
|
|
92
|
-
phase: 'updating',
|
|
93
|
-
});
|
|
94
|
-
return;
|
|
90
|
+
throw new Error('Too many re-renders.');
|
|
95
91
|
}
|
|
96
92
|
lifecycleEventBus.publish({ type: 'beforeRender', element: nextElement, phase: 'updating' });
|
|
97
93
|
batchingRerenderLocker.lock();
|
|
@@ -103,26 +99,19 @@ function patchFunctionalComponent(prevElement, nextElement, parentReference, nex
|
|
|
103
99
|
}
|
|
104
100
|
catch (error) {
|
|
105
101
|
lifecycleEventBus.publish({ type: 'errored', element: nextElement, error, phase: 'updating' });
|
|
102
|
+
remove(prevElement, parentReference);
|
|
106
103
|
return;
|
|
107
104
|
}
|
|
108
105
|
finally {
|
|
109
106
|
triedToRerenderUnsubscribe();
|
|
110
107
|
}
|
|
108
|
+
// Keep prevElement's children reference when prev and next elements are identical to avoid reassignment.
|
|
111
109
|
const prevChildren = prevElement.children;
|
|
112
110
|
if (nextChildren) {
|
|
113
111
|
nextElement.children = nextChildren;
|
|
114
112
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
lifecycleEventBus.publish({ type: 'updated', element: nextElement });
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
prevElement.unmounted = false;
|
|
121
|
-
if (nextChildren) {
|
|
122
|
-
nextChildren.parent = nextElement;
|
|
123
|
-
mount(nextChildren, parentReference, nextReference, contextMap, hostNamespace);
|
|
124
|
-
}
|
|
125
|
-
lifecycleEventBus.publish({ type: 'mounted', element: nextElement });
|
|
113
|
+
patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, nextElement.context, hostNamespace);
|
|
114
|
+
lifecycleEventBus.publish({ type: 'updated', element: nextElement });
|
|
126
115
|
}
|
|
127
116
|
function patchTextElement(prevElement, nextElement) {
|
|
128
117
|
nextElement.reference = prevElement.reference;
|
|
@@ -130,57 +119,41 @@ function patchTextElement(prevElement, nextElement) {
|
|
|
130
119
|
hostAdapter.setTextContent(nextElement.reference, nextElement.children);
|
|
131
120
|
}
|
|
132
121
|
}
|
|
133
|
-
function patchFragment(prevElement, nextElement, parentReference,
|
|
134
|
-
let nextReference = null;
|
|
135
|
-
if (Array.isArray(prevElement.children) && !Array.isArray(nextElement.children) && nextElement.children) {
|
|
136
|
-
nextReference = hostAdapter.findNextSiblingReference(findHostReferenceFromElement(prevElement.children[prevElement.children.length - 1]));
|
|
137
|
-
}
|
|
138
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, contextMap, hostNamespace);
|
|
139
|
-
}
|
|
140
|
-
function patchProvider(prevElement, nextElement, parentReference, contextMap, hostNamespace) {
|
|
122
|
+
function patchFragment(prevElement, nextElement, parentReference, context, hostNamespace) {
|
|
141
123
|
let nextReference = null;
|
|
142
124
|
if (Array.isArray(prevElement.children) && !Array.isArray(nextElement.children) && nextElement.children) {
|
|
143
125
|
nextReference = hostAdapter.findNextSiblingReference(findHostReferenceFromElement(prevElement.children[prevElement.children.length - 1]));
|
|
144
126
|
}
|
|
145
|
-
|
|
146
|
-
contextMap.set(nextElement.type.context, nextElement.props.value);
|
|
147
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, contextMap, hostNamespace);
|
|
148
|
-
}
|
|
149
|
-
function patchConsumer(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace) {
|
|
150
|
-
const children = normalizeRoot(nextElement.type(nextElement.props || emptyObject, contextMap || emptyMap), false);
|
|
151
|
-
if (children) {
|
|
152
|
-
nextElement.children = children;
|
|
153
|
-
}
|
|
154
|
-
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, contextMap, hostNamespace);
|
|
127
|
+
patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, context, hostNamespace);
|
|
155
128
|
}
|
|
156
|
-
export function patchPortal(prevElement, nextElement,
|
|
129
|
+
export function patchPortal(prevElement, nextElement, context) {
|
|
157
130
|
const prevContainer = prevElement.ref;
|
|
158
131
|
const nextContainer = nextElement.ref;
|
|
159
132
|
const nextChildren = nextElement.children;
|
|
160
|
-
patchChildren(prevElement.children, nextChildren, prevContainer, null, nextElement,
|
|
133
|
+
patchChildren(prevElement.children, nextChildren, prevContainer, null, nextElement, context, hostAdapter.getHostNamespaces(nextChildren, undefined)?.self);
|
|
161
134
|
nextElement.reference = prevElement.reference;
|
|
162
135
|
if (prevContainer !== nextContainer && nextChildren != null) {
|
|
163
136
|
hostAdapter.removeChild(prevContainer, nextChildren.reference);
|
|
164
137
|
hostAdapter.appendChild(nextContainer, nextChildren.reference);
|
|
165
138
|
}
|
|
166
139
|
}
|
|
167
|
-
export function updateFunctionalComponent(element, parentReference, nextReference,
|
|
168
|
-
patchFunctionalComponent(element, element, parentReference, nextReference,
|
|
140
|
+
export function updateFunctionalComponent(element, parentReference, nextReference, context, hostNamespace) {
|
|
141
|
+
patchFunctionalComponent(element, element, parentReference, nextReference, context, hostNamespace);
|
|
169
142
|
}
|
|
170
|
-
function patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement,
|
|
143
|
+
function patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, context, hostNamespace) {
|
|
171
144
|
if (Array.isArray(prevChildren)) {
|
|
172
145
|
if (Array.isArray(nextChildren)) {
|
|
173
146
|
for (const child of nextChildren) {
|
|
174
147
|
child.parent = nextElement;
|
|
175
148
|
}
|
|
176
|
-
patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference,
|
|
149
|
+
patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
177
150
|
}
|
|
178
151
|
else if (typeof nextChildren === 'string') {
|
|
179
152
|
unmount(prevChildren);
|
|
180
153
|
hostAdapter.setTextContent(parentReference, nextChildren);
|
|
181
154
|
}
|
|
182
155
|
else if (nextChildren) {
|
|
183
|
-
patchKeyedChildren(prevChildren, [nextChildren], parentReference, nextReference,
|
|
156
|
+
patchKeyedChildren(prevChildren, [nextChildren], parentReference, nextReference, context, hostNamespace);
|
|
184
157
|
}
|
|
185
158
|
else {
|
|
186
159
|
unmount(prevChildren);
|
|
@@ -190,7 +163,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
|
|
|
190
163
|
else if (typeof prevChildren === 'string') {
|
|
191
164
|
if (Array.isArray(nextChildren)) {
|
|
192
165
|
hostAdapter.clearNode(parentReference);
|
|
193
|
-
mountArrayChildren(nextChildren, parentReference, nextReference,
|
|
166
|
+
mountArrayChildren(nextChildren, parentReference, nextReference, context, nextElement, hostNamespace);
|
|
194
167
|
}
|
|
195
168
|
else if (typeof nextChildren === 'string') {
|
|
196
169
|
if (prevChildren !== nextChildren) {
|
|
@@ -200,7 +173,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
|
|
|
200
173
|
else if (nextChildren) {
|
|
201
174
|
hostAdapter.clearNode(parentReference);
|
|
202
175
|
nextChildren.parent = nextElement;
|
|
203
|
-
mount(nextChildren, parentReference, nextReference,
|
|
176
|
+
mount(nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
204
177
|
}
|
|
205
178
|
else {
|
|
206
179
|
hostAdapter.clearNode(parentReference);
|
|
@@ -208,7 +181,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
|
|
|
208
181
|
}
|
|
209
182
|
else if (prevChildren) {
|
|
210
183
|
if (Array.isArray(nextChildren)) {
|
|
211
|
-
patchKeyedChildren([prevChildren], nextChildren, parentReference, nextReference,
|
|
184
|
+
patchKeyedChildren([prevChildren], nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
212
185
|
}
|
|
213
186
|
else if (typeof nextChildren === 'string') {
|
|
214
187
|
unmount(prevChildren);
|
|
@@ -216,7 +189,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
|
|
|
216
189
|
}
|
|
217
190
|
else if (nextChildren) {
|
|
218
191
|
nextChildren.parent = nextElement;
|
|
219
|
-
patch(prevChildren, nextChildren, parentReference, nextReference,
|
|
192
|
+
patch(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
220
193
|
}
|
|
221
194
|
else {
|
|
222
195
|
remove(prevChildren, parentReference);
|
|
@@ -224,18 +197,18 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
|
|
|
224
197
|
}
|
|
225
198
|
else {
|
|
226
199
|
if (Array.isArray(nextChildren)) {
|
|
227
|
-
mountArrayChildren(nextChildren, parentReference, nextReference,
|
|
200
|
+
mountArrayChildren(nextChildren, parentReference, nextReference, context, nextElement, hostNamespace);
|
|
228
201
|
}
|
|
229
202
|
else if (typeof nextChildren === 'string') {
|
|
230
203
|
hostAdapter.setTextContent(parentReference, nextChildren);
|
|
231
204
|
}
|
|
232
205
|
else if (nextChildren) {
|
|
233
206
|
nextChildren.parent = nextElement;
|
|
234
|
-
mount(nextChildren, parentReference, nextReference,
|
|
207
|
+
mount(nextChildren, parentReference, nextReference, context, hostNamespace);
|
|
235
208
|
}
|
|
236
209
|
}
|
|
237
210
|
}
|
|
238
|
-
export function patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference,
|
|
211
|
+
export function patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace) {
|
|
239
212
|
let prevStart = 0;
|
|
240
213
|
let nextStart = 0;
|
|
241
214
|
let prevEnd = prevChildren.length - 1;
|
|
@@ -244,13 +217,13 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
244
217
|
while (prevStart <= prevEnd &&
|
|
245
218
|
nextStart <= nextEnd &&
|
|
246
219
|
prevChildren[prevStart].key === nextChildren[nextStart].key) {
|
|
247
|
-
patch(prevChildren[prevStart], nextChildren[nextStart], parentReference, null,
|
|
220
|
+
patch(prevChildren[prevStart], nextChildren[nextStart], parentReference, null, context, hostNamespace);
|
|
248
221
|
prevStart++;
|
|
249
222
|
nextStart++;
|
|
250
223
|
}
|
|
251
224
|
// Step 2: Sync from end
|
|
252
225
|
while (prevStart <= prevEnd && nextStart <= nextEnd && prevChildren[prevEnd].key === nextChildren[nextEnd].key) {
|
|
253
|
-
patch(prevChildren[prevEnd], nextChildren[nextEnd], parentReference, null,
|
|
226
|
+
patch(prevChildren[prevEnd], nextChildren[nextEnd], parentReference, null, context, hostNamespace);
|
|
254
227
|
prevEnd--;
|
|
255
228
|
nextEnd--;
|
|
256
229
|
}
|
|
@@ -258,7 +231,7 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
258
231
|
if (prevStart > prevEnd) {
|
|
259
232
|
const before = findHostReferenceFromElement(nextChildren[nextEnd + 1]) || nextReference;
|
|
260
233
|
for (let i = nextStart; i <= nextEnd; i++) {
|
|
261
|
-
mount(nextChildren[i], parentReference, before,
|
|
234
|
+
mount(nextChildren[i], parentReference, before, context, hostNamespace);
|
|
262
235
|
}
|
|
263
236
|
// Step 4: Remove prev nodes if next list is exhausted
|
|
264
237
|
}
|
|
@@ -286,12 +259,12 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
|
|
|
286
259
|
const prevIndex = keyToPrevIndexMap.get(nextChild.key);
|
|
287
260
|
if (prevIndex != null) {
|
|
288
261
|
const prevElement = prevChildren[prevIndex];
|
|
289
|
-
patch(prevElement, nextChild, parentReference, null,
|
|
262
|
+
patch(prevElement, nextChild, parentReference, null, context, hostNamespace);
|
|
290
263
|
toMove[i - nextStart] = prevIndex;
|
|
291
264
|
usedIndices.add(prevIndex);
|
|
292
265
|
}
|
|
293
266
|
else {
|
|
294
|
-
mount(nextChild, parentReference, findHostReferenceFromElement(nextChildren[i + 1]) || nextReference,
|
|
267
|
+
mount(nextChild, parentReference, findHostReferenceFromElement(nextChildren[i + 1]) || nextReference, context, hostNamespace);
|
|
295
268
|
toMove[i - nextStart] = -1;
|
|
296
269
|
}
|
|
297
270
|
}
|
package/core/rerender.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
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
|
-
|
|
7
|
-
|
|
5
|
+
_elementStores: Set<SimpElementStore>;
|
|
6
|
+
_last: SimpElementStore | undefined;
|
|
7
|
+
_track(element: SimpElementStore): void;
|
|
8
|
+
_untrack(element: SimpElementStore): void;
|
|
8
9
|
lock(): void;
|
|
9
10
|
flush(): void;
|
|
10
11
|
}
|
package/core/rerender.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { findParentReferenceFromElement, updateFunctionalComponent } from './patching.js';
|
|
2
2
|
import { lifecycleEventBus } from './lifecycleEventBus.js';
|
|
3
3
|
lifecycleEventBus.subscribe(event => {
|
|
4
|
-
if (event.type === 'afterRender') {
|
|
5
|
-
batchingRerenderLocker._untrack(event.element);
|
|
6
|
-
renderingRerenderLocker._untrack(event.element);
|
|
4
|
+
if (event.type === 'afterRender' || event.type === 'errored' || event.type === 'unmounted') {
|
|
5
|
+
batchingRerenderLocker._untrack(event.element.store);
|
|
6
|
+
renderingRerenderLocker._untrack(event.element.store);
|
|
7
7
|
}
|
|
8
8
|
});
|
|
9
9
|
export function rerender(element) {
|
|
@@ -15,62 +15,114 @@ export function rerender(element) {
|
|
|
15
15
|
}
|
|
16
16
|
lifecycleEventBus.publish({ type: 'triedToRerender', element });
|
|
17
17
|
if (batchingRerenderLocker._isLocked) {
|
|
18
|
-
batchingRerenderLocker._track(element);
|
|
18
|
+
batchingRerenderLocker._track(element.store);
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
21
|
if (renderingRerenderLocker._isLocked) {
|
|
22
|
-
renderingRerenderLocker._track(element);
|
|
22
|
+
renderingRerenderLocker._track(element.store);
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
25
|
renderingRerenderLocker.lock();
|
|
26
|
-
updateFunctionalComponent(element, findParentReferenceFromElement(element), null, element.
|
|
26
|
+
updateFunctionalComponent(element, findParentReferenceFromElement(element), null, element.context || null, element.store.hostNamespace);
|
|
27
27
|
renderingRerenderLocker.flush();
|
|
28
28
|
}
|
|
29
29
|
export const batchingRerenderLocker = {
|
|
30
30
|
_isLocked: false,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
_elementStores: new Set(),
|
|
32
|
+
_last: undefined,
|
|
33
|
+
_track(store) {
|
|
34
|
+
if (this._elementStores.has(store)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (this._elementStores.size === 0 || store.forceRender) {
|
|
38
|
+
this._elementStores.add(store);
|
|
39
|
+
this._last = store;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (isParentOf(store.latestElement, this._last.latestElement)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (isParentOf(this._last.latestElement, store.latestElement)) {
|
|
46
|
+
this._elementStores.clear();
|
|
47
|
+
this._elementStores.add(store);
|
|
48
|
+
this._last = store;
|
|
49
|
+
}
|
|
34
50
|
},
|
|
35
|
-
_untrack(
|
|
36
|
-
this.
|
|
51
|
+
_untrack(store) {
|
|
52
|
+
if (this._elementStores.delete(store) && store === this._last) {
|
|
53
|
+
this._last = undefined;
|
|
54
|
+
for (const val of this._elementStores) {
|
|
55
|
+
this._last = val;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
37
58
|
},
|
|
38
59
|
lock() {
|
|
39
60
|
this._isLocked = true;
|
|
40
61
|
},
|
|
41
62
|
flush() {
|
|
42
63
|
this._isLocked = false;
|
|
43
|
-
if (this.
|
|
64
|
+
if (this._elementStores.size === 0) {
|
|
44
65
|
return;
|
|
45
66
|
}
|
|
46
|
-
for (const
|
|
47
|
-
this._untrack(
|
|
48
|
-
rerender(
|
|
67
|
+
for (const store of this._elementStores) {
|
|
68
|
+
this._untrack(store);
|
|
69
|
+
rerender(store.latestElement);
|
|
49
70
|
}
|
|
50
71
|
},
|
|
51
72
|
};
|
|
52
73
|
export const renderingRerenderLocker = {
|
|
53
74
|
_isLocked: false,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
75
|
+
_elementStores: new Set(),
|
|
76
|
+
_last: undefined,
|
|
77
|
+
_track(store) {
|
|
78
|
+
if (this._elementStores.has(store)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (this._elementStores.size === 0 || store.forceRender) {
|
|
82
|
+
this._elementStores.add(store);
|
|
83
|
+
this._last = store;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (isParentOf(store.latestElement, this._last.latestElement)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (isParentOf(this._last.latestElement, store.latestElement)) {
|
|
90
|
+
this._elementStores.clear();
|
|
91
|
+
this._elementStores.add(store);
|
|
92
|
+
this._last = store;
|
|
93
|
+
}
|
|
57
94
|
},
|
|
58
|
-
_untrack(
|
|
59
|
-
this.
|
|
95
|
+
_untrack(store) {
|
|
96
|
+
if (this._elementStores.delete(store) && store === this._last) {
|
|
97
|
+
this._last = undefined;
|
|
98
|
+
for (const val of this._elementStores) {
|
|
99
|
+
this._last = val;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
60
102
|
},
|
|
61
103
|
lock() {
|
|
62
104
|
this._isLocked = true;
|
|
63
105
|
},
|
|
64
106
|
flush() {
|
|
65
107
|
this._isLocked = false;
|
|
66
|
-
if (this.
|
|
108
|
+
if (this._elementStores.size === 0) {
|
|
67
109
|
return;
|
|
68
110
|
}
|
|
69
111
|
queueMicrotask(() => {
|
|
70
|
-
for (const
|
|
71
|
-
this._untrack(
|
|
72
|
-
rerender(
|
|
112
|
+
for (const store of this._elementStores) {
|
|
113
|
+
this._untrack(store);
|
|
114
|
+
rerender(store.latestElement);
|
|
73
115
|
}
|
|
74
116
|
});
|
|
75
117
|
},
|
|
76
118
|
};
|
|
119
|
+
function isParentOf(element, parent) {
|
|
120
|
+
let current = element.parent;
|
|
121
|
+
while (current) {
|
|
122
|
+
if (current.store === parent.store) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
current = current.parent;
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
}
|
package/core/unmounting.js
CHANGED
|
@@ -28,7 +28,7 @@ export function unmount(element) {
|
|
|
28
28
|
remove(element.children, element.ref);
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
|
-
// Only FRAGMENT
|
|
31
|
+
// Only FRAGMENT and HOST elements remain,
|
|
32
32
|
// with Maybe<Many<SimpElement>> children due to normalization.
|
|
33
33
|
if (element.children) {
|
|
34
34
|
unmount(element.children);
|
|
@@ -45,11 +45,11 @@ export function clearElementHostReference(element, parentHostReference) {
|
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
const children = element.children;
|
|
48
|
-
if (element.flag === 'FC'
|
|
48
|
+
if (element.flag === 'FC') {
|
|
49
49
|
element = children;
|
|
50
50
|
continue;
|
|
51
51
|
}
|
|
52
|
-
if (element.flag === 'FRAGMENT'
|
|
52
|
+
if (element.flag === 'FRAGMENT') {
|
|
53
53
|
if (Array.isArray(children)) {
|
|
54
54
|
for (let i = 0, len = children.length; i < len; ++i) {
|
|
55
55
|
clearElementHostReference(children[i], parentHostReference);
|
|
@@ -5,5 +5,14 @@ export function attachElementToDom(element, dom) {
|
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
7
|
export function getElementFromDom(target) {
|
|
8
|
-
|
|
8
|
+
if (!target) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
while (target && !(elementPropertyName in target)) {
|
|
12
|
+
target = target.parentElement;
|
|
13
|
+
}
|
|
14
|
+
if (!target) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return target[elementPropertyName];
|
|
9
18
|
}
|
package/dom/events.d.ts
CHANGED
|
@@ -4,15 +4,20 @@ export declare class SyntheticEvent {
|
|
|
4
4
|
nativeEvent: Event;
|
|
5
5
|
currentTarget: Nullable<EventTarget>;
|
|
6
6
|
isPropagationStopped: boolean;
|
|
7
|
-
|
|
7
|
+
_isDefaultPrevented: boolean;
|
|
8
8
|
button?: number;
|
|
9
9
|
buttons?: number;
|
|
10
10
|
pointerId?: number;
|
|
11
|
+
altKey?: boolean;
|
|
12
|
+
ctrlKey?: boolean;
|
|
13
|
+
shiftKey?: boolean;
|
|
14
|
+
metaKey?: boolean;
|
|
11
15
|
constructor(event: Event);
|
|
12
16
|
get target(): EventTarget | null;
|
|
13
17
|
get type(): string;
|
|
14
18
|
stopPropagation(): void;
|
|
15
19
|
preventDefault(): void;
|
|
20
|
+
isDefaultPrevented(): boolean;
|
|
16
21
|
}
|
|
17
22
|
export declare function dispatchDelegatedEvent(event: Event): void;
|
|
18
23
|
export declare function patchEvent(name: string, prevValue: any, nextValue: any, dom: Element): void;
|
package/dom/events.js
CHANGED
|
@@ -39,15 +39,22 @@ export class SyntheticEvent {
|
|
|
39
39
|
nativeEvent;
|
|
40
40
|
currentTarget = null;
|
|
41
41
|
isPropagationStopped = false;
|
|
42
|
-
|
|
42
|
+
_isDefaultPrevented = false;
|
|
43
43
|
button;
|
|
44
44
|
buttons;
|
|
45
45
|
pointerId;
|
|
46
|
+
altKey;
|
|
47
|
+
ctrlKey;
|
|
48
|
+
shiftKey;
|
|
49
|
+
metaKey;
|
|
46
50
|
constructor(event) {
|
|
47
51
|
this.nativeEvent = event;
|
|
48
52
|
this.button = event.button;
|
|
49
53
|
this.buttons = event.buttons;
|
|
50
54
|
this.pointerId = event.pointerId;
|
|
55
|
+
this.altKey = event.altKey;
|
|
56
|
+
this.ctrlKey = event.ctrlKey;
|
|
57
|
+
this.metaKey = event.metaKey;
|
|
51
58
|
}
|
|
52
59
|
get target() {
|
|
53
60
|
return this.nativeEvent.target;
|
|
@@ -60,9 +67,12 @@ export class SyntheticEvent {
|
|
|
60
67
|
this.nativeEvent.stopPropagation();
|
|
61
68
|
}
|
|
62
69
|
preventDefault() {
|
|
63
|
-
this.
|
|
70
|
+
this._isDefaultPrevented = true;
|
|
64
71
|
this.nativeEvent.preventDefault();
|
|
65
72
|
}
|
|
73
|
+
isDefaultPrevented() {
|
|
74
|
+
return this._isDefaultPrevented;
|
|
75
|
+
}
|
|
66
76
|
}
|
|
67
77
|
export function dispatchDelegatedEvent(event) {
|
|
68
78
|
batchingRerenderLocker.lock();
|
package/hooks/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RefObject
|
|
1
|
+
import type { RefObject } from '../core/index.js';
|
|
2
2
|
|
|
3
3
|
export type Cleanup = () => void;
|
|
4
4
|
export type Effect = () => void | Cleanup;
|
|
@@ -22,8 +22,6 @@ declare function useMounted(effect: Effect): void;
|
|
|
22
22
|
|
|
23
23
|
declare function useUnmounted(cleanup: Cleanup): void;
|
|
24
24
|
|
|
25
|
-
declare function useContext<T>(context: SimpContext<T>): T;
|
|
26
|
-
|
|
27
25
|
declare function useCatch(cb: (error: any) => void): void;
|
|
28
26
|
|
|
29
27
|
declare function areDepsEqual(nextDeps: DependencyList | undefined, prevDeps: DependencyList | undefined): boolean;
|
package/hooks/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { batchingRerenderLocker, lifecycleEventBus, rerender as _rerender } from '../core/internal.js';
|
|
2
|
-
import { noop } from '../shared/index.js';
|
|
3
|
-
import { callOrGet } from '../shared/utils.js';
|
|
2
|
+
import { callOrGet, noop } from '../shared/index.js';
|
|
4
3
|
let currentIndex = 0;
|
|
5
4
|
// In runtime this is a nullable variable.
|
|
6
5
|
let currentElement;
|
|
@@ -48,7 +47,9 @@ lifecycleEventBus.subscribe(event => {
|
|
|
48
47
|
if (event.type === 'unmounted') {
|
|
49
48
|
const element = event.element;
|
|
50
49
|
if (element.store?.hookStates) {
|
|
51
|
-
|
|
50
|
+
const hookStates = element.store.hookStates;
|
|
51
|
+
element.store.hookStates = undefined;
|
|
52
|
+
for (const state of hookStates) {
|
|
52
53
|
if (state && 'cleanup' in state && typeof state.cleanup === 'function') {
|
|
53
54
|
state.cleanup();
|
|
54
55
|
}
|
|
@@ -91,6 +92,7 @@ export function useRerender() {
|
|
|
91
92
|
if (!hookStates[currentIndex]) {
|
|
92
93
|
const elementStore = currentElement.store;
|
|
93
94
|
hookStates[currentIndex] = function rerender() {
|
|
95
|
+
elementStore.forceRender = true;
|
|
94
96
|
_rerender(elementStore.latestElement);
|
|
95
97
|
};
|
|
96
98
|
}
|
|
@@ -108,6 +110,7 @@ export function useState(initialState) {
|
|
|
108
110
|
return;
|
|
109
111
|
}
|
|
110
112
|
state[0] = nextValue;
|
|
113
|
+
elementStore.forceRender = true;
|
|
111
114
|
_rerender(elementStore.latestElement);
|
|
112
115
|
};
|
|
113
116
|
}
|
|
@@ -141,9 +144,6 @@ export function useUnmounted(cleanup) {
|
|
|
141
144
|
}
|
|
142
145
|
currentIndex++;
|
|
143
146
|
}
|
|
144
|
-
export function useContext(context) {
|
|
145
|
-
return currentElement.contextMap?.get(context) ?? context.defaultValue;
|
|
146
|
-
}
|
|
147
147
|
export function useCatch(cb) {
|
|
148
148
|
if (!currentElement.store) {
|
|
149
149
|
currentElement.store = {};
|
|
@@ -189,7 +189,6 @@ export default {
|
|
|
189
189
|
useEffect,
|
|
190
190
|
useMounted,
|
|
191
191
|
useUnmounted,
|
|
192
|
-
useContext,
|
|
193
192
|
useCatch,
|
|
194
193
|
areDepsEqual,
|
|
195
194
|
};
|