@simpreact/simpreact 0.0.5 → 0.0.7
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 +9 -5
- 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 +12 -9
- package/compat/index.js +3 -0
- package/compat/renderRuntime.d.ts +6 -0
- package/compat/renderRuntime.js +17 -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 +20 -6
- package/core/internal.d.ts +5 -0
- package/core/internal.js +5 -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 +6 -9
- package/core/mounting.js +177 -86
- package/core/mountingChildren.d.ts +4 -0
- package/core/mountingChildren.js +47 -0
- package/core/patching.d.ts +7 -8
- package/core/patching.js +245 -252
- package/core/patchingChildren.d.ts +6 -0
- package/core/patchingChildren.js +343 -0
- package/core/portal.d.ts +1 -1
- package/core/portal.js +17 -7
- package/core/processStack.d.ts +106 -0
- package/core/processStack.js +75 -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 +6 -5
- package/core/unmounting.js +58 -57
- package/core/unmountingChildren.d.ts +4 -0
- package/core/unmountingChildren.js +23 -0
- package/core/utils.d.ts +11 -0
- package/core/utils.js +168 -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 +5 -5
- package/dom/props/dangerInnerHTML.js +10 -15
- 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 +154 -157
- 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,7 @@
|
|
|
1
|
-
import type { Many, Maybe } from '../shared/index.js';
|
|
2
1
|
import type { SimpElement } from './createElement.js';
|
|
3
|
-
import type
|
|
4
|
-
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
2
|
+
import { type UnmountFrame, type UnmountFrameMeta } from './processStack.js';
|
|
3
|
+
import type { SimpRenderRuntime } from './runtime.js';
|
|
4
|
+
export declare function unmount(element: SimpElement, renderRuntime: SimpRenderRuntime): void;
|
|
5
|
+
export declare function _unmount(frame: UnmountFrame): void;
|
|
6
|
+
export declare function _pushUnmountEnterFrame(element: SimpElement, meta: UnmountFrameMeta): void;
|
|
7
|
+
export declare function _pushUnmountExitFrame(element: SimpElement, meta: UnmountFrameMeta): void;
|
package/core/unmounting.js
CHANGED
|
@@ -1,68 +1,69 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { unmountRef } from './ref.js';
|
|
1
|
+
import { noop } from '../shared/index.js';
|
|
3
2
|
import { lifecycleEventBus } from './lifecycleEventBus.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
import { processStack, UNMOUNT_ENTER, UNMOUNT_EXIT } from './processStack.js';
|
|
4
|
+
import { unmountRef } from './ref.js';
|
|
5
|
+
import { _pushUnmountChildrenFrame } from './unmountingChildren.js';
|
|
6
|
+
import { _clearElementHostReference, bitScanForwardIndex } from './utils.js';
|
|
7
|
+
const unmountHandlers = [
|
|
8
|
+
_unmountHostElement,
|
|
9
|
+
_unmountFunctionalElement,
|
|
10
|
+
noop,
|
|
11
|
+
_unmountPortalElement,
|
|
12
|
+
_unmountFragmentElement,
|
|
13
|
+
];
|
|
14
|
+
export function unmount(element, renderRuntime) {
|
|
15
|
+
if (renderRuntime.renderStack.length !== 0) {
|
|
16
|
+
throw new Error('Cannot unmount while rendering.');
|
|
10
17
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
_pushUnmountEnterFrame(element, { renderRuntime });
|
|
19
|
+
processStack(renderRuntime);
|
|
20
|
+
}
|
|
21
|
+
export function _unmount(frame) {
|
|
22
|
+
unmountHandlers[bitScanForwardIndex(frame.node.flag)](frame);
|
|
23
|
+
}
|
|
24
|
+
export function _pushUnmountEnterFrame(element, meta) {
|
|
25
|
+
meta.renderRuntime.renderStack.push({
|
|
26
|
+
node: element,
|
|
27
|
+
kind: UNMOUNT_ENTER,
|
|
28
|
+
meta,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export function _pushUnmountExitFrame(element, meta) {
|
|
32
|
+
meta.renderRuntime.renderStack.push({
|
|
33
|
+
node: element,
|
|
34
|
+
kind: UNMOUNT_EXIT,
|
|
35
|
+
meta,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function _unmountFunctionalElement(frame) {
|
|
39
|
+
const current = frame.node;
|
|
40
|
+
if (current.unmounted) {
|
|
22
41
|
return;
|
|
23
42
|
}
|
|
24
|
-
if (
|
|
43
|
+
if (frame.kind === UNMOUNT_EXIT) {
|
|
44
|
+
current.unmounted = true;
|
|
45
|
+
lifecycleEventBus.publish({ type: 'unmounted', element: current, renderRuntime: frame.meta.renderRuntime });
|
|
46
|
+
current.store = null;
|
|
25
47
|
return;
|
|
26
48
|
}
|
|
27
|
-
|
|
28
|
-
|
|
49
|
+
_pushUnmountExitFrame(current, frame.meta);
|
|
50
|
+
_pushUnmountChildrenFrame(current, frame.meta);
|
|
51
|
+
}
|
|
52
|
+
function _unmountHostElement(frame) {
|
|
53
|
+
const current = frame.node;
|
|
54
|
+
if (frame.kind === UNMOUNT_EXIT) {
|
|
55
|
+
unmountRef(current);
|
|
56
|
+
frame.meta.renderRuntime.hostAdapter.unmountProps(current.reference, current, frame.meta.renderRuntime);
|
|
57
|
+
frame.meta.renderRuntime.hostAdapter.detachElementFromReference(current.reference, frame.meta.renderRuntime);
|
|
29
58
|
return;
|
|
30
59
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (element.children) {
|
|
34
|
-
unmount(element.children);
|
|
35
|
-
}
|
|
36
|
-
if (element.flag === 'HOST') {
|
|
37
|
-
unmountRef(element);
|
|
38
|
-
hostAdapter.unmountProps(element.reference, element);
|
|
39
|
-
}
|
|
60
|
+
_pushUnmountExitFrame(current, frame.meta);
|
|
61
|
+
_pushUnmountChildrenFrame(current, frame.meta);
|
|
40
62
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
hostAdapter.removeChild(parentHostReference, element.reference);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
const children = element.children;
|
|
48
|
-
if (element.flag === 'FC') {
|
|
49
|
-
element = children;
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (element.flag === 'FRAGMENT') {
|
|
53
|
-
if (Array.isArray(children)) {
|
|
54
|
-
for (let i = 0, len = children.length; i < len; ++i) {
|
|
55
|
-
clearElementHostReference(children[i], parentHostReference);
|
|
56
|
-
}
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
else if (children) {
|
|
60
|
-
element = children;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
63
|
+
function _unmountPortalElement(frame) {
|
|
64
|
+
_clearElementHostReference(frame.node.children, frame.node.ref, frame.meta.renderRuntime);
|
|
65
|
+
_pushUnmountChildrenFrame(frame.node, frame.meta);
|
|
64
66
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
clearElementHostReference(element, parentReference);
|
|
67
|
+
function _unmountFragmentElement(frame) {
|
|
68
|
+
_pushUnmountChildrenFrame(frame.node, frame.meta);
|
|
68
69
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type SimpElement } from './createElement.js';
|
|
2
|
+
import { type UnmountChildrenFrame, type UnmountFrameMeta } from './processStack.js';
|
|
3
|
+
export declare function _pushUnmountChildrenFrame(parent: SimpElement, meta: UnmountFrameMeta): void;
|
|
4
|
+
export declare function _unmountChildren(frame: UnmountChildrenFrame): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SIMP_ELEMENT_CHILD_FLAG_ELEMENT, SIMP_ELEMENT_CHILD_FLAG_LIST } from './createElement.js';
|
|
2
|
+
import { UNMOUNT_CHILDREN_ENTER } from './processStack.js';
|
|
3
|
+
import { _pushUnmountEnterFrame } from './unmounting.js';
|
|
4
|
+
export function _pushUnmountChildrenFrame(parent, meta) {
|
|
5
|
+
meta.renderRuntime.renderStack.push({
|
|
6
|
+
node: parent,
|
|
7
|
+
kind: UNMOUNT_CHILDREN_ENTER,
|
|
8
|
+
meta,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export function _unmountChildren(frame) {
|
|
12
|
+
switch (frame.node.childFlag) {
|
|
13
|
+
case SIMP_ELEMENT_CHILD_FLAG_LIST:
|
|
14
|
+
const children = frame.node.children;
|
|
15
|
+
for (let i = children.length - 1; i >= 0; i -= 1) {
|
|
16
|
+
_pushUnmountEnterFrame(children[i], frame.meta);
|
|
17
|
+
}
|
|
18
|
+
break;
|
|
19
|
+
case SIMP_ELEMENT_CHILD_FLAG_ELEMENT:
|
|
20
|
+
_pushUnmountEnterFrame(frame.node.children, frame.meta);
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
package/core/utils.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Maybe, 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(subtreeRightBoundary: Nullable<SimpElement>): unknown | null;
|
|
9
|
+
export declare function findHostReferenceFromElement(element: Nullable<SimpElement>): unknown | null;
|
|
10
|
+
export declare function getLongestIncreasingSubsequenceIndexes(sequence: Int32Array): Int32Array;
|
|
11
|
+
export declare function _clearElementHostReference(element: Maybe<SimpElement>, parentHostReference: unknown, renderRuntime: SimpRenderRuntime): void;
|
package/core/utils.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
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';
|
|
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(subtreeRightBoundary) {
|
|
47
|
+
let current = subtreeRightBoundary;
|
|
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
|
+
}
|
|
144
|
+
export function _clearElementHostReference(element, parentHostReference, renderRuntime) {
|
|
145
|
+
while (element != null) {
|
|
146
|
+
if (isHostLike(element.flag)) {
|
|
147
|
+
renderRuntime.hostAdapter.removeChild(parentHostReference, element.reference);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const children = element.children;
|
|
151
|
+
const childFlag = element.childFlag;
|
|
152
|
+
if ((element.flag & SIMP_ELEMENT_FLAG_FC) !== 0) {
|
|
153
|
+
element = children;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if ((element.flag & SIMP_ELEMENT_FLAG_FRAGMENT) !== 0) {
|
|
157
|
+
switch (childFlag) {
|
|
158
|
+
case SIMP_ELEMENT_CHILD_FLAG_LIST:
|
|
159
|
+
for (let i = 0, len = children.length; i < len; ++i) {
|
|
160
|
+
_clearElementHostReference(children[i], parentHostReference, renderRuntime);
|
|
161
|
+
}
|
|
162
|
+
return;
|
|
163
|
+
case SIMP_ELEMENT_CHILD_FLAG_ELEMENT:
|
|
164
|
+
element = children;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -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
|
}
|