@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.
Files changed (83) hide show
  1. package/LICENSE.txt +1 -1
  2. package/compat/context.d.ts +4 -4
  3. package/compat/context.js +3 -2
  4. package/compat/core.d.ts +4 -0
  5. package/compat/core.js +9 -5
  6. package/compat/dom.d.ts +4 -5
  7. package/compat/dom.js +3 -2
  8. package/compat/hooks.d.ts +16 -13
  9. package/compat/hooks.js +19 -15
  10. package/compat/index.d.ts +12 -9
  11. package/compat/index.js +3 -0
  12. package/compat/renderRuntime.d.ts +6 -0
  13. package/compat/renderRuntime.js +17 -0
  14. package/component/index.d.ts +16 -0
  15. package/component/index.js +164 -0
  16. package/context/index.d.ts +12 -5
  17. package/context/index.js +62 -57
  18. package/core/createElement.d.ts +29 -20
  19. package/core/createElement.js +159 -133
  20. package/core/hostAdapter.d.ts +8 -12
  21. package/core/hostAdapter.js +1 -4
  22. package/core/hostOperations.d.ts +5 -0
  23. package/core/hostOperations.js +15 -0
  24. package/core/index.d.ts +20 -6
  25. package/core/internal.d.ts +5 -0
  26. package/core/internal.js +5 -0
  27. package/core/lifecycleEventBus.d.ts +15 -6
  28. package/core/lifecycleEventBus.js +16 -2
  29. package/core/memo.d.ts +0 -2
  30. package/core/memo.js +1 -3
  31. package/core/mounting.d.ts +6 -9
  32. package/core/mounting.js +177 -86
  33. package/core/mountingChildren.d.ts +4 -0
  34. package/core/mountingChildren.js +47 -0
  35. package/core/patching.d.ts +7 -8
  36. package/core/patching.js +245 -252
  37. package/core/patchingChildren.d.ts +6 -0
  38. package/core/patchingChildren.js +343 -0
  39. package/core/portal.d.ts +1 -1
  40. package/core/portal.js +17 -7
  41. package/core/processStack.d.ts +106 -0
  42. package/core/processStack.js +75 -0
  43. package/core/ref.d.ts +4 -3
  44. package/core/rerender.d.ts +4 -14
  45. package/core/rerender.js +67 -112
  46. package/core/runtime.d.ts +17 -0
  47. package/core/runtime.js +2 -0
  48. package/core/unmounting.d.ts +6 -5
  49. package/core/unmounting.js +58 -57
  50. package/core/unmountingChildren.d.ts +4 -0
  51. package/core/unmountingChildren.js +23 -0
  52. package/core/utils.d.ts +11 -0
  53. package/core/utils.js +168 -0
  54. package/dom/attach-element-to-dom.d.ts +4 -3
  55. package/dom/attach-element-to-dom.js +12 -7
  56. package/dom/domAdapter.js +22 -25
  57. package/dom/events.d.ts +5 -5
  58. package/dom/events.js +33 -16
  59. package/dom/index.d.ts +16 -5
  60. package/dom/index.js +4 -3
  61. package/dom/props/controlled/index.d.ts +3 -3
  62. package/dom/props/controlled/index.js +8 -8
  63. package/dom/props/controlled/input.d.ts +3 -3
  64. package/dom/props/controlled/input.js +57 -34
  65. package/dom/props/controlled/select.d.ts +3 -3
  66. package/dom/props/controlled/select.js +39 -26
  67. package/dom/props/controlled/textarea.d.ts +3 -3
  68. package/dom/props/controlled/textarea.js +57 -34
  69. package/dom/props/dangerInnerHTML.d.ts +5 -5
  70. package/dom/props/dangerInnerHTML.js +10 -15
  71. package/dom/props/props.d.ts +4 -4
  72. package/dom/props/props.js +24 -21
  73. package/dom/render.d.ts +4 -5
  74. package/dom/render.js +38 -34
  75. package/hooks/index.d.ts +15 -13
  76. package/hooks/index.js +154 -157
  77. package/jsx-runtime/index.d.ts +2 -1
  78. package/package.json +9 -1
  79. package/shared/index.d.ts +10 -0
  80. package/shared/index.js +4 -7
  81. package/shared/utils.js +4 -4
  82. package/shared/EventBus.d.ts +0 -18
  83. 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
- batchingRerenderLocker._untrack(event.element.store);
6
- renderingRerenderLocker._untrack(event.element.store);
21
+ data.asyncQueue.delete(event.element.store);
22
+ data.syncQueue.delete(event.element.store);
7
23
  }
8
24
  });
9
- export function rerender(element) {
10
- if (element.flag !== 'FC') {
11
- throw new TypeError('Re-rendering is only supported for FC elements.');
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
- if (renderingRerenderLocker._isLocked) {
22
- renderingRerenderLocker._track(element.store);
48
+ lifecycleEventBus.publish({ type: 'triedToRerender', element, renderRuntime });
49
+ if (data.syncLockDepth > 0) {
50
+ data.syncQueue.add(store);
23
51
  return;
24
52
  }
25
- renderingRerenderLocker.lock();
26
- updateFunctionalComponent(element, findParentReferenceFromElement(element), null, element.context || null, element.store.hostNamespace);
27
- renderingRerenderLocker.flush();
53
+ data.asyncQueue.add(store);
54
+ scheduleAsyncFlush(renderRuntime);
28
55
  }
29
- export const batchingRerenderLocker = {
30
- _isLocked: false,
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
- }
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
- return false;
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
+ }
@@ -0,0 +1,2 @@
1
+ export const MOUNTING_PHASE = 0;
2
+ export const UPDATING_PHASE = 1;
@@ -1,6 +1,7 @@
1
- import type { Many, Maybe } from '../shared/index.js';
2
1
  import type { SimpElement } from './createElement.js';
3
- import type { HostReference } from './hostAdapter.js';
4
- export declare function unmount(element: Many<SimpElement>): void;
5
- export declare function clearElementHostReference(element: Maybe<SimpElement>, parentHostReference: HostReference): void;
6
- export declare function remove(element: SimpElement, parentReference: HostReference): void;
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;
@@ -1,68 +1,69 @@
1
- import { hostAdapter } from './hostAdapter.js';
2
- import { unmountRef } from './ref.js';
1
+ import { noop } from '../shared/index.js';
3
2
  import { lifecycleEventBus } from './lifecycleEventBus.js';
4
- export function unmount(element) {
5
- if (Array.isArray(element)) {
6
- for (const child of element) {
7
- unmount(child);
8
- }
9
- return;
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
- if (element.flag === 'FC') {
12
- // Skip — element is already unmounted.
13
- if (element.unmounted) {
14
- return;
15
- }
16
- // FC element always has Maybe<SimpElement> due to normalization.
17
- if (element.children) {
18
- unmount(element.children);
19
- }
20
- element.unmounted = true;
21
- lifecycleEventBus.publish({ type: 'unmounted', element });
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 (element.flag === 'TEXT') {
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
- if (element.flag === 'PORTAL') {
28
- remove(element.children, element.ref);
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
- // Only FRAGMENT and HOST elements remain,
32
- // with Maybe<Many<SimpElement>> children due to normalization.
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
- export function clearElementHostReference(element, parentHostReference) {
42
- while (element != null) {
43
- if (element.flag === 'HOST' || element.flag === 'TEXT' || element.flag === 'PORTAL') {
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
- export function remove(element, parentReference) {
66
- unmount(element);
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
+ }
@@ -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
- 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>;
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
- const elementPropertyName = '__SIMP_ELEMENT__';
2
- export function attachElementToDom(element, dom) {
3
- if (element.flag !== 'TEXT') {
4
- Object.defineProperty(dom, elementPropertyName, { value: element, writable: true });
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 && !(elementPropertyName in 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[elementPropertyName];
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
  }