@simpreact/simpreact 0.0.4 → 0.0.6
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/LICENSE.txt +1 -1
- package/compat/context.d.ts +4 -4
- package/compat/context.js +3 -2
- package/compat/core.d.ts +4 -0
- package/compat/core.js +14 -9
- package/compat/dom.d.ts +4 -5
- package/compat/dom.js +3 -2
- package/compat/hooks.d.ts +16 -13
- package/compat/hooks.js +19 -15
- package/compat/index.d.ts +10 -9
- package/compat/renderRuntime.d.ts +2 -0
- package/compat/renderRuntime.js +14 -0
- package/component/index.d.ts +16 -0
- package/component/index.js +164 -0
- package/context/index.d.ts +12 -5
- package/context/index.js +62 -57
- package/core/createElement.d.ts +29 -20
- package/core/createElement.js +159 -133
- package/core/hostAdapter.d.ts +8 -12
- package/core/hostAdapter.js +1 -4
- package/core/hostOperations.d.ts +5 -0
- package/core/hostOperations.js +15 -0
- package/core/index.d.ts +29 -6
- package/core/internal.d.ts +3 -0
- package/core/internal.js +3 -0
- package/core/lifecycleEventBus.d.ts +15 -6
- package/core/lifecycleEventBus.js +16 -2
- package/core/memo.d.ts +0 -2
- package/core/memo.js +1 -3
- package/core/mounting.d.ts +7 -9
- package/core/mounting.js +221 -82
- package/core/patching.d.ts +7 -8
- package/core/patching.js +235 -255
- package/core/patchingChildren.d.ts +6 -0
- package/core/patchingChildren.js +330 -0
- package/core/portal.d.ts +1 -1
- package/core/portal.js +17 -7
- package/core/processStack.d.ts +69 -0
- package/core/processStack.js +63 -0
- package/core/ref.d.ts +4 -3
- package/core/rerender.d.ts +4 -14
- package/core/rerender.js +67 -112
- package/core/runtime.d.ts +17 -0
- package/core/runtime.js +2 -0
- package/core/unmounting.d.ts +11 -6
- package/core/unmounting.js +81 -40
- package/core/utils.d.ts +10 -0
- package/core/utils.js +143 -0
- package/dom/attach-element-to-dom.d.ts +4 -3
- package/dom/attach-element-to-dom.js +12 -7
- package/dom/domAdapter.js +22 -25
- package/dom/events.d.ts +5 -5
- package/dom/events.js +33 -16
- package/dom/index.d.ts +16 -5
- package/dom/index.js +4 -3
- package/dom/props/controlled/index.d.ts +3 -3
- package/dom/props/controlled/index.js +8 -8
- package/dom/props/controlled/input.d.ts +3 -3
- package/dom/props/controlled/input.js +57 -34
- package/dom/props/controlled/select.d.ts +3 -3
- package/dom/props/controlled/select.js +39 -26
- package/dom/props/controlled/textarea.d.ts +3 -3
- package/dom/props/controlled/textarea.js +57 -34
- package/dom/props/dangerInnerHTML.d.ts +2 -2
- package/dom/props/dangerInnerHTML.js +3 -2
- package/dom/props/props.d.ts +4 -4
- package/dom/props/props.js +24 -21
- package/dom/render.d.ts +4 -5
- package/dom/render.js +38 -34
- package/hooks/index.d.ts +15 -13
- package/hooks/index.js +155 -159
- package/jsx-runtime/index.d.ts +2 -1
- package/package.json +9 -1
- package/shared/index.d.ts +10 -0
- package/shared/index.js +4 -7
- package/shared/utils.js +4 -4
- package/shared/EventBus.d.ts +0 -18
- package/shared/EventBus.js +0 -28
package/core/rerender.js
CHANGED
|
@@ -1,128 +1,83 @@
|
|
|
1
|
-
import { findParentReferenceFromElement, updateFunctionalComponent } from './patching.js';
|
|
2
1
|
import { lifecycleEventBus } from './lifecycleEventBus.js';
|
|
2
|
+
import { patch } from './patching.js';
|
|
3
|
+
import { findParentReferenceFromElement } from './utils.js';
|
|
4
|
+
const rerenderSpecificDataByRuntime = new WeakMap();
|
|
5
|
+
function getRerenderSpecificData(renderRuntime) {
|
|
6
|
+
let data = rerenderSpecificDataByRuntime.get(renderRuntime);
|
|
7
|
+
if (!data) {
|
|
8
|
+
data = {
|
|
9
|
+
asyncQueue: new Set(),
|
|
10
|
+
syncQueue: new Set(),
|
|
11
|
+
syncLockDepth: 0,
|
|
12
|
+
isAsyncFlushScheduled: false,
|
|
13
|
+
};
|
|
14
|
+
rerenderSpecificDataByRuntime.set(renderRuntime, data);
|
|
15
|
+
}
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
3
18
|
lifecycleEventBus.subscribe(event => {
|
|
19
|
+
const data = getRerenderSpecificData(event.renderRuntime);
|
|
4
20
|
if (event.type === 'afterRender' || event.type === 'errored' || event.type === 'unmounted') {
|
|
5
|
-
|
|
6
|
-
|
|
21
|
+
data.asyncQueue.delete(event.element.store);
|
|
22
|
+
data.syncQueue.delete(event.element.store);
|
|
7
23
|
}
|
|
8
24
|
});
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
25
|
+
function scheduleAsyncFlush(renderRuntime) {
|
|
26
|
+
const data = getRerenderSpecificData(renderRuntime);
|
|
27
|
+
if (data.isAsyncFlushScheduled) {
|
|
28
|
+
return;
|
|
12
29
|
}
|
|
30
|
+
data.isAsyncFlushScheduled = true;
|
|
31
|
+
const process = () => {
|
|
32
|
+
if (data.asyncQueue.size === 0) {
|
|
33
|
+
data.isAsyncFlushScheduled = false;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
flushQueue(data.asyncQueue, renderRuntime);
|
|
37
|
+
queueMicrotask(process);
|
|
38
|
+
};
|
|
39
|
+
queueMicrotask(process);
|
|
40
|
+
}
|
|
41
|
+
export function rerender(store, renderRuntime) {
|
|
42
|
+
const data = getRerenderSpecificData(renderRuntime);
|
|
43
|
+
const element = store.latestElement;
|
|
13
44
|
if (element.unmounted) {
|
|
14
45
|
console.warn('The component is unmounted.');
|
|
15
|
-
}
|
|
16
|
-
lifecycleEventBus.publish({ type: 'triedToRerender', element });
|
|
17
|
-
if (batchingRerenderLocker._isLocked) {
|
|
18
|
-
batchingRerenderLocker._track(element.store);
|
|
19
46
|
return;
|
|
20
47
|
}
|
|
21
|
-
|
|
22
|
-
|
|
48
|
+
lifecycleEventBus.publish({ type: 'triedToRerender', element, renderRuntime });
|
|
49
|
+
if (data.syncLockDepth > 0) {
|
|
50
|
+
data.syncQueue.add(store);
|
|
23
51
|
return;
|
|
24
52
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
renderingRerenderLocker.flush();
|
|
53
|
+
data.asyncQueue.add(store);
|
|
54
|
+
scheduleAsyncFlush(renderRuntime);
|
|
28
55
|
}
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (
|
|
38
|
-
|
|
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
|
-
}
|
|
50
|
-
},
|
|
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
|
-
}
|
|
58
|
-
},
|
|
59
|
-
lock() {
|
|
60
|
-
this._isLocked = true;
|
|
61
|
-
},
|
|
62
|
-
flush() {
|
|
63
|
-
this._isLocked = false;
|
|
64
|
-
if (this._elementStores.size === 0) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
for (const store of this._elementStores) {
|
|
68
|
-
this._untrack(store);
|
|
69
|
-
rerender(store.latestElement);
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
export const renderingRerenderLocker = {
|
|
74
|
-
_isLocked: false,
|
|
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
|
-
}
|
|
94
|
-
},
|
|
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
|
-
}
|
|
102
|
-
},
|
|
103
|
-
lock() {
|
|
104
|
-
this._isLocked = true;
|
|
105
|
-
},
|
|
106
|
-
flush() {
|
|
107
|
-
this._isLocked = false;
|
|
108
|
-
if (this._elementStores.size === 0) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
queueMicrotask(() => {
|
|
112
|
-
for (const store of this._elementStores) {
|
|
113
|
-
this._untrack(store);
|
|
114
|
-
rerender(store.latestElement);
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
function isParentOf(element, parent) {
|
|
120
|
-
let current = element.parent;
|
|
121
|
-
while (current) {
|
|
122
|
-
if (current.store === parent.store) {
|
|
123
|
-
return true;
|
|
56
|
+
export function withSyncRerender(renderRuntime, callback) {
|
|
57
|
+
const data = getRerenderSpecificData(renderRuntime);
|
|
58
|
+
data.syncLockDepth++;
|
|
59
|
+
try {
|
|
60
|
+
callback();
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
data.syncLockDepth--;
|
|
64
|
+
if (data.syncLockDepth === 0) {
|
|
65
|
+
flushQueue(data.syncQueue, renderRuntime);
|
|
124
66
|
}
|
|
125
|
-
current = current.parent;
|
|
126
67
|
}
|
|
127
|
-
|
|
68
|
+
}
|
|
69
|
+
function flushQueue(queue, renderRuntime) {
|
|
70
|
+
for (const store of queue) {
|
|
71
|
+
queue.delete(store);
|
|
72
|
+
performRerender(store.latestElement, renderRuntime);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function performRerender(element, renderRuntime) {
|
|
76
|
+
element.store.forceRerender = true;
|
|
77
|
+
try {
|
|
78
|
+
patch(element, element, findParentReferenceFromElement(element), null, element.context || null, element.store.hostNamespace, renderRuntime);
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
element.store.forceRerender = false;
|
|
82
|
+
}
|
|
128
83
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Nullable } from '../shared/index.js';
|
|
2
|
+
import type { FC, SimpElement, SimpNode } from './createElement.js';
|
|
3
|
+
import type { HostAdapter } from './hostAdapter.js';
|
|
4
|
+
import type { SimpRenderStack } from './processStack.js';
|
|
5
|
+
export interface SimpRuntimeFCRenderer {
|
|
6
|
+
(component: FC, element: SimpElement, renderRuntime: SimpRenderRuntime): SimpNode;
|
|
7
|
+
}
|
|
8
|
+
export declare const MOUNTING_PHASE = 0;
|
|
9
|
+
export declare const UPDATING_PHASE = 1;
|
|
10
|
+
export interface SimpRenderRuntime {
|
|
11
|
+
hostAdapter: HostAdapter;
|
|
12
|
+
renderer: SimpRuntimeFCRenderer;
|
|
13
|
+
renderStack: SimpRenderStack;
|
|
14
|
+
elementToHostMap: Map<unknown, SimpElement>;
|
|
15
|
+
currentRenderingFCElement: Nullable<SimpElement>;
|
|
16
|
+
renderPhase: Nullable<typeof MOUNTING_PHASE | typeof UPDATING_PHASE>;
|
|
17
|
+
}
|
package/core/runtime.js
ADDED
package/core/unmounting.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type
|
|
3
|
-
import type
|
|
4
|
-
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
1
|
+
import type { Maybe } from '../shared/index.js';
|
|
2
|
+
import { type SimpElement } from './createElement.js';
|
|
3
|
+
import { type UnmountFrame } from './processStack.js';
|
|
4
|
+
import type { SimpRenderRuntime } from './runtime.js';
|
|
5
|
+
export declare function unmount(element: SimpElement, renderRuntime: SimpRenderRuntime): void;
|
|
6
|
+
export declare function _unmount(frame: UnmountFrame): void;
|
|
7
|
+
export declare function _pushUnmountEnterFrame(element: SimpElement, renderRuntime: SimpRenderRuntime): void;
|
|
8
|
+
export declare function _pushUnmountExitFrame(element: SimpElement, renderRuntime: SimpRenderRuntime): void;
|
|
9
|
+
export declare function _pushUnmountArrayChildrenFrame(element: SimpElement, renderRuntime: SimpRenderRuntime): void;
|
|
10
|
+
export declare function _clearElementHostReference(element: Maybe<SimpElement>, parentHostReference: unknown, renderRuntime: SimpRenderRuntime): void;
|
|
11
|
+
export declare function _remove(element: SimpElement, parentReference: unknown, renderRuntime: SimpRenderRuntime): void;
|
package/core/unmounting.js
CHANGED
|
@@ -1,68 +1,109 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { unmountRef } from './ref.js';
|
|
1
|
+
import { SIMP_ELEMENT_CHILD_FLAG_ELEMENT, SIMP_ELEMENT_CHILD_FLAG_LIST, SIMP_ELEMENT_FLAG_FC, SIMP_ELEMENT_FLAG_FRAGMENT, SIMP_ELEMENT_FLAG_HOST, SIMP_ELEMENT_FLAG_PORTAL, SIMP_ELEMENT_FLAG_TEXT, } from './createElement.js';
|
|
3
2
|
import { lifecycleEventBus } from './lifecycleEventBus.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
import { processStack, UNMOUNT_ENTER, UNMOUNT_EXIT } from './processStack.js';
|
|
4
|
+
import { unmountRef } from './ref.js';
|
|
5
|
+
import { isHostLike } from './utils.js';
|
|
6
|
+
export function unmount(element, renderRuntime) {
|
|
7
|
+
if (renderRuntime.renderStack.length !== 0) {
|
|
8
|
+
throw new Error('Cannot unmount while rendering.');
|
|
9
|
+
}
|
|
10
|
+
_pushUnmountEnterFrame(element, renderRuntime);
|
|
11
|
+
processStack(renderRuntime);
|
|
12
|
+
}
|
|
13
|
+
export function _unmount(frame) {
|
|
14
|
+
const current = frame.node;
|
|
15
|
+
if (frame.kind === UNMOUNT_EXIT) {
|
|
16
|
+
if ((current.flag & SIMP_ELEMENT_FLAG_FC) !== 0) {
|
|
17
|
+
current.unmounted = true;
|
|
18
|
+
lifecycleEventBus.publish({ type: 'unmounted', element: current, renderRuntime: frame.meta.renderRuntime });
|
|
19
|
+
current.store = null;
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if ((current.flag & SIMP_ELEMENT_FLAG_HOST) !== 0) {
|
|
23
|
+
unmountRef(current);
|
|
24
|
+
frame.meta.renderRuntime.hostAdapter.unmountProps(current.reference, current, frame.meta.renderRuntime);
|
|
25
|
+
frame.meta.renderRuntime.hostAdapter.detachElementFromReference(current.reference, frame.meta.renderRuntime);
|
|
8
26
|
}
|
|
9
27
|
return;
|
|
10
28
|
}
|
|
11
|
-
if (
|
|
12
|
-
|
|
13
|
-
if (element.unmounted) {
|
|
29
|
+
if ((current.flag & SIMP_ELEMENT_FLAG_FC) !== 0) {
|
|
30
|
+
if (current.unmounted) {
|
|
14
31
|
return;
|
|
15
32
|
}
|
|
16
|
-
|
|
17
|
-
if (
|
|
18
|
-
|
|
33
|
+
_pushUnmountExitFrame(current, frame.meta.renderRuntime);
|
|
34
|
+
if (current.children) {
|
|
35
|
+
_pushUnmountEnterFrame(current.children, frame.meta.renderRuntime);
|
|
19
36
|
}
|
|
20
|
-
element.unmounted = true;
|
|
21
|
-
lifecycleEventBus.publish({ type: 'unmounted', element });
|
|
22
37
|
return;
|
|
23
38
|
}
|
|
24
|
-
if (
|
|
39
|
+
if ((current.flag & SIMP_ELEMENT_FLAG_TEXT) !== 0) {
|
|
25
40
|
return;
|
|
26
41
|
}
|
|
27
|
-
if (
|
|
28
|
-
|
|
42
|
+
if ((current.flag & SIMP_ELEMENT_FLAG_PORTAL) !== 0) {
|
|
43
|
+
_remove(current.children, current.ref, frame.meta.renderRuntime);
|
|
29
44
|
return;
|
|
30
45
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (element.children) {
|
|
34
|
-
unmount(element.children);
|
|
46
|
+
if ((current.flag & SIMP_ELEMENT_FLAG_HOST) !== 0) {
|
|
47
|
+
_pushUnmountExitFrame(current, frame.meta.renderRuntime);
|
|
35
48
|
}
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
49
|
+
if (current.childFlag === SIMP_ELEMENT_CHILD_FLAG_ELEMENT) {
|
|
50
|
+
_pushUnmountEnterFrame(current.children, frame.meta.renderRuntime);
|
|
51
|
+
return;
|
|
39
52
|
}
|
|
53
|
+
if (current.childFlag === SIMP_ELEMENT_CHILD_FLAG_LIST) {
|
|
54
|
+
_pushUnmountArrayChildrenFrame(current, frame.meta.renderRuntime);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function _pushUnmountEnterFrame(element, renderRuntime) {
|
|
58
|
+
renderRuntime.renderStack.push({
|
|
59
|
+
node: element,
|
|
60
|
+
kind: UNMOUNT_ENTER,
|
|
61
|
+
meta: {
|
|
62
|
+
renderRuntime,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export function _pushUnmountExitFrame(element, renderRuntime) {
|
|
67
|
+
renderRuntime.renderStack.push({
|
|
68
|
+
node: element,
|
|
69
|
+
kind: UNMOUNT_EXIT,
|
|
70
|
+
meta: {
|
|
71
|
+
renderRuntime,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
40
74
|
}
|
|
41
|
-
export function
|
|
75
|
+
export function _pushUnmountArrayChildrenFrame(element, renderRuntime) {
|
|
76
|
+
const children = element.children;
|
|
77
|
+
for (let i = children.length - 1; i >= 0; i -= 1) {
|
|
78
|
+
_pushUnmountEnterFrame(children[i], renderRuntime);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export function _clearElementHostReference(element, parentHostReference, renderRuntime) {
|
|
42
82
|
while (element != null) {
|
|
43
|
-
if (element.flag
|
|
44
|
-
hostAdapter.removeChild(parentHostReference, element.reference);
|
|
83
|
+
if (isHostLike(element.flag)) {
|
|
84
|
+
renderRuntime.hostAdapter.removeChild(parentHostReference, element.reference);
|
|
45
85
|
return;
|
|
46
86
|
}
|
|
47
87
|
const children = element.children;
|
|
48
|
-
|
|
88
|
+
const childFlag = element.childFlag;
|
|
89
|
+
if ((element.flag & SIMP_ELEMENT_FLAG_FC) !== 0) {
|
|
49
90
|
element = children;
|
|
50
91
|
continue;
|
|
51
92
|
}
|
|
52
|
-
if (element.flag
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
93
|
+
if ((element.flag & SIMP_ELEMENT_FLAG_FRAGMENT) !== 0) {
|
|
94
|
+
switch (childFlag) {
|
|
95
|
+
case SIMP_ELEMENT_CHILD_FLAG_LIST:
|
|
96
|
+
for (let i = 0, len = children.length; i < len; ++i) {
|
|
97
|
+
_clearElementHostReference(children[i], parentHostReference, renderRuntime);
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
case SIMP_ELEMENT_CHILD_FLAG_ELEMENT:
|
|
101
|
+
element = children;
|
|
61
102
|
}
|
|
62
103
|
}
|
|
63
104
|
}
|
|
64
105
|
}
|
|
65
|
-
export function
|
|
66
|
-
|
|
67
|
-
|
|
106
|
+
export function _remove(element, parentReference, renderRuntime) {
|
|
107
|
+
_clearElementHostReference(element, parentReference, renderRuntime);
|
|
108
|
+
_pushUnmountEnterFrame(element, renderRuntime);
|
|
68
109
|
}
|
package/core/utils.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Nullable } from '../shared/index.js';
|
|
2
|
+
import { type SimpElement } from './createElement.js';
|
|
3
|
+
import type { SimpRenderRuntime } from './runtime.js';
|
|
4
|
+
export declare function bitScanForwardIndex(flag: number): number;
|
|
5
|
+
export declare function isHostLike(flag: number): boolean;
|
|
6
|
+
export declare function findParentReferenceFromElement(element: SimpElement): unknown | null;
|
|
7
|
+
export declare function placeElementBeforeAnchor(element: SimpElement, anchor: unknown, parentReference: unknown, renderRuntime: SimpRenderRuntime): void;
|
|
8
|
+
export declare function resolveAnchorReference(rightSibling: Nullable<SimpElement>): unknown | null;
|
|
9
|
+
export declare function findHostReferenceFromElement(element: Nullable<SimpElement>): unknown | null;
|
|
10
|
+
export declare function getLongestIncreasingSubsequenceIndexes(sequence: Int32Array): Int32Array;
|
package/core/utils.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { SIMP_ELEMENT_CHILD_FLAG_ELEMENT, SIMP_ELEMENT_CHILD_FLAG_LIST, SIMP_ELEMENT_FLAG_HOST, SIMP_ELEMENT_FLAG_PORTAL, SIMP_ELEMENT_FLAG_TEXT, } from './createElement.js';
|
|
2
|
+
export function bitScanForwardIndex(flag) {
|
|
3
|
+
const lsb = (flag & -flag) >>> 0;
|
|
4
|
+
return 31 - Math.clz32(lsb);
|
|
5
|
+
}
|
|
6
|
+
export function isHostLike(flag) {
|
|
7
|
+
return ((flag & SIMP_ELEMENT_FLAG_HOST) !== 0 ||
|
|
8
|
+
(flag & SIMP_ELEMENT_FLAG_TEXT) !== 0 ||
|
|
9
|
+
(flag & SIMP_ELEMENT_FLAG_PORTAL) !== 0);
|
|
10
|
+
}
|
|
11
|
+
export function findParentReferenceFromElement(element) {
|
|
12
|
+
let flag;
|
|
13
|
+
let temp = element;
|
|
14
|
+
while (temp != null) {
|
|
15
|
+
flag = temp.flag;
|
|
16
|
+
if ((flag & SIMP_ELEMENT_FLAG_HOST) !== 0) {
|
|
17
|
+
return temp.reference;
|
|
18
|
+
}
|
|
19
|
+
temp = temp.parent;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const placeStack = [];
|
|
24
|
+
export function placeElementBeforeAnchor(element, anchor, parentReference, renderRuntime) {
|
|
25
|
+
const { hostAdapter } = renderRuntime;
|
|
26
|
+
placeStack.push(element);
|
|
27
|
+
let nextAnchor = anchor;
|
|
28
|
+
while (placeStack.length !== 0) {
|
|
29
|
+
const current = placeStack.pop();
|
|
30
|
+
if (isHostLike(current.flag)) {
|
|
31
|
+
hostAdapter.insertOrAppend(parentReference, current.reference, nextAnchor);
|
|
32
|
+
nextAnchor = current.reference;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (current.childFlag === SIMP_ELEMENT_CHILD_FLAG_LIST) {
|
|
36
|
+
const children = current.children;
|
|
37
|
+
for (let i = 0; i < children.length; i++) {
|
|
38
|
+
placeStack.push(children[i]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (current.childFlag === SIMP_ELEMENT_CHILD_FLAG_ELEMENT) {
|
|
42
|
+
placeStack.push(current.children);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function resolveAnchorReference(rightSibling) {
|
|
47
|
+
let current = rightSibling;
|
|
48
|
+
while (current != null) {
|
|
49
|
+
const reference = findHostReferenceFromElement(current);
|
|
50
|
+
if (reference != null) {
|
|
51
|
+
return reference;
|
|
52
|
+
}
|
|
53
|
+
current = findNextLogicalElement(current);
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
export function findHostReferenceFromElement(element) {
|
|
58
|
+
if (element == null) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const stack = [element];
|
|
62
|
+
while (stack.length) {
|
|
63
|
+
const node = stack.pop();
|
|
64
|
+
if (node == null) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (isHostLike(node.flag)) {
|
|
68
|
+
return node.reference;
|
|
69
|
+
}
|
|
70
|
+
if (node.childFlag === SIMP_ELEMENT_CHILD_FLAG_LIST) {
|
|
71
|
+
const list = node.children;
|
|
72
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
73
|
+
stack.push(list[i]);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (node.childFlag === SIMP_ELEMENT_CHILD_FLAG_ELEMENT) {
|
|
77
|
+
stack.push(node.children);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
function findNextLogicalElement(element) {
|
|
83
|
+
let current = element;
|
|
84
|
+
while (true) {
|
|
85
|
+
const parent = current.parent;
|
|
86
|
+
if (parent == null || isHostLike(parent.flag)) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
if (parent.childFlag !== SIMP_ELEMENT_CHILD_FLAG_LIST) {
|
|
90
|
+
current = parent;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const nextSibling = parent.children[current.index + 1];
|
|
94
|
+
if (nextSibling != null) {
|
|
95
|
+
return nextSibling;
|
|
96
|
+
}
|
|
97
|
+
current = parent;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export function getLongestIncreasingSubsequenceIndexes(sequence) {
|
|
101
|
+
const predecessors = new Int32Array(sequence.length);
|
|
102
|
+
const result = [];
|
|
103
|
+
predecessors.fill(-1);
|
|
104
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
105
|
+
const value = sequence[i];
|
|
106
|
+
if (value === 0) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const lastResultIndex = result[result.length - 1];
|
|
110
|
+
if (lastResultIndex == null || sequence[lastResultIndex] < value) {
|
|
111
|
+
if (lastResultIndex != null) {
|
|
112
|
+
predecessors[i] = lastResultIndex;
|
|
113
|
+
}
|
|
114
|
+
result.push(i);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
let start = 0;
|
|
118
|
+
let end = result.length - 1;
|
|
119
|
+
while (start < end) {
|
|
120
|
+
const middle = (start + end) >> 1;
|
|
121
|
+
if (sequence[result[middle]] < value) {
|
|
122
|
+
start = middle + 1;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
end = middle;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (value < sequence[result[start]]) {
|
|
129
|
+
if (start > 0) {
|
|
130
|
+
predecessors[i] = result[start - 1];
|
|
131
|
+
}
|
|
132
|
+
result[start] = i;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
let resultIndex = result.length;
|
|
136
|
+
let sequenceIndex = result[resultIndex - 1] ?? -1;
|
|
137
|
+
const indexes = new Int32Array(resultIndex);
|
|
138
|
+
while (resultIndex-- > 0) {
|
|
139
|
+
indexes[resultIndex] = sequenceIndex;
|
|
140
|
+
sequenceIndex = predecessors[sequenceIndex];
|
|
141
|
+
}
|
|
142
|
+
return indexes;
|
|
143
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { type SimpElement, type SimpRenderRuntime } from '../core/internal.js';
|
|
1
2
|
import type { Nullable } from '../shared/index.js';
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
3
|
+
export declare function attachElementToDom(element: SimpElement, dom: Node, renderRuntime: SimpRenderRuntime): void;
|
|
4
|
+
export declare function getElementFromDom(target: Nullable<EventTarget>, renderRuntime: SimpRenderRuntime): Nullable<SimpElement>;
|
|
5
|
+
export declare function detachElementFromDom(dom: Node, renderRuntime: SimpRenderRuntime): void;
|
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
export function attachElementToDom(element, dom) {
|
|
3
|
-
if (element.flag
|
|
4
|
-
|
|
1
|
+
import { SIMP_ELEMENT_FLAG_TEXT } from '../core/internal.js';
|
|
2
|
+
export function attachElementToDom(element, dom, renderRuntime) {
|
|
3
|
+
if ((element.flag & SIMP_ELEMENT_FLAG_TEXT) === 0) {
|
|
4
|
+
renderRuntime.elementToHostMap.set(dom, element);
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
-
export function getElementFromDom(target) {
|
|
7
|
+
export function getElementFromDom(target, renderRuntime) {
|
|
8
8
|
if (!target) {
|
|
9
9
|
return null;
|
|
10
10
|
}
|
|
11
|
-
while (target && !(
|
|
11
|
+
while (target && !renderRuntime.elementToHostMap.has(target)) {
|
|
12
12
|
target = target.parentElement;
|
|
13
13
|
}
|
|
14
14
|
if (!target) {
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
|
-
return target
|
|
17
|
+
return renderRuntime.elementToHostMap.get(target);
|
|
18
|
+
}
|
|
19
|
+
export function detachElementFromDom(dom, renderRuntime) {
|
|
20
|
+
if (renderRuntime.elementToHostMap.has(dom)) {
|
|
21
|
+
renderRuntime.elementToHostMap.delete(dom);
|
|
22
|
+
}
|
|
18
23
|
}
|
package/dom/domAdapter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { attachElementToDom } from './attach-element-to-dom.js';
|
|
2
|
-
import { mountProps, patchProps, unmountProps } from './props/index.js';
|
|
1
|
+
import { attachElementToDom, detachElementFromDom, getElementFromDom } from './attach-element-to-dom.js';
|
|
3
2
|
import { defaultNamespace } from './namespace.js';
|
|
3
|
+
import { mountProps, patchProps, unmountProps } from './props/index.js';
|
|
4
4
|
export const domAdapter = {
|
|
5
5
|
createReference(type, namespace) {
|
|
6
6
|
if (namespace) {
|
|
@@ -13,14 +13,14 @@ export const domAdapter = {
|
|
|
13
13
|
createTextReference(text) {
|
|
14
14
|
return document.createTextNode(text);
|
|
15
15
|
},
|
|
16
|
-
mountProps(dom, element, namespace) {
|
|
17
|
-
mountProps(dom, element, namespace || defaultNamespace);
|
|
16
|
+
mountProps(dom, element, renderRuntime, namespace) {
|
|
17
|
+
mountProps(dom, element, namespace || defaultNamespace, renderRuntime);
|
|
18
18
|
},
|
|
19
|
-
patchProps(dom, prevElement, nextElement, namespace) {
|
|
20
|
-
patchProps(dom, prevElement, nextElement, namespace || defaultNamespace);
|
|
19
|
+
patchProps(dom, prevElement, nextElement, renderRuntime, namespace) {
|
|
20
|
+
patchProps(dom, prevElement, nextElement, namespace || defaultNamespace, renderRuntime);
|
|
21
21
|
},
|
|
22
|
-
unmountProps(dom, element) {
|
|
23
|
-
unmountProps(dom, element);
|
|
22
|
+
unmountProps(dom, element, renderRuntime) {
|
|
23
|
+
unmountProps(dom, element, renderRuntime);
|
|
24
24
|
},
|
|
25
25
|
setClassname(reference, className, namespace) {
|
|
26
26
|
if (!className) {
|
|
@@ -41,18 +41,12 @@ export const domAdapter = {
|
|
|
41
41
|
reference.textContent = text;
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
-
appendChild(parent, child) {
|
|
45
|
-
parent.appendChild(child);
|
|
46
|
-
},
|
|
47
|
-
insertBefore(parent, child, before) {
|
|
48
|
-
parent.insertBefore(child, before);
|
|
49
|
-
},
|
|
50
44
|
insertOrAppend(parent, child, before) {
|
|
51
45
|
if (before) {
|
|
52
|
-
|
|
46
|
+
parent.insertBefore(child, before);
|
|
53
47
|
}
|
|
54
48
|
else {
|
|
55
|
-
|
|
49
|
+
parent.appendChild(child);
|
|
56
50
|
}
|
|
57
51
|
},
|
|
58
52
|
removeChild(parent, child) {
|
|
@@ -61,21 +55,24 @@ export const domAdapter = {
|
|
|
61
55
|
replaceChild(parent, replacer, toBeReplaced) {
|
|
62
56
|
parent.replaceChild(replacer, toBeReplaced);
|
|
63
57
|
},
|
|
64
|
-
findParentReference(reference) {
|
|
65
|
-
return reference.parentElement;
|
|
66
|
-
},
|
|
67
|
-
findNextSiblingReference(reference) {
|
|
68
|
-
return reference.nextSibling;
|
|
69
|
-
},
|
|
70
58
|
clearNode(reference) {
|
|
71
59
|
reference.textContent = '';
|
|
72
60
|
},
|
|
73
|
-
attachElementToReference(element, reference) {
|
|
74
|
-
attachElementToDom(element, reference);
|
|
61
|
+
attachElementToReference(element, reference, renderRuntime) {
|
|
62
|
+
attachElementToDom(element, reference, renderRuntime);
|
|
63
|
+
},
|
|
64
|
+
getElementFromReference(reference, renderRuntime) {
|
|
65
|
+
return getElementFromDom(reference, renderRuntime);
|
|
66
|
+
},
|
|
67
|
+
detachElementFromReference(reference, renderRuntime) {
|
|
68
|
+
detachElementFromDom(reference, renderRuntime);
|
|
75
69
|
},
|
|
76
70
|
getHostNamespaces(element, currentNamespace) {
|
|
77
71
|
if (element.type === 'svg') {
|
|
78
|
-
return {
|
|
72
|
+
return {
|
|
73
|
+
self: 'http://www.w3.org/2000/svg',
|
|
74
|
+
children: 'http://www.w3.org/2000/svg',
|
|
75
|
+
};
|
|
79
76
|
}
|
|
80
77
|
if (element.type === 'foreignObject') {
|
|
81
78
|
return { self: 'http://www.w3.org/2000/svg', children: null };
|