@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.
Files changed (78) 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 +14 -9
  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 +10 -9
  11. package/compat/renderRuntime.d.ts +2 -0
  12. package/compat/renderRuntime.js +14 -0
  13. package/component/index.d.ts +16 -0
  14. package/component/index.js +164 -0
  15. package/context/index.d.ts +12 -5
  16. package/context/index.js +62 -57
  17. package/core/createElement.d.ts +29 -20
  18. package/core/createElement.js +159 -133
  19. package/core/hostAdapter.d.ts +8 -12
  20. package/core/hostAdapter.js +1 -4
  21. package/core/hostOperations.d.ts +5 -0
  22. package/core/hostOperations.js +15 -0
  23. package/core/index.d.ts +29 -6
  24. package/core/internal.d.ts +3 -0
  25. package/core/internal.js +3 -0
  26. package/core/lifecycleEventBus.d.ts +15 -6
  27. package/core/lifecycleEventBus.js +16 -2
  28. package/core/memo.d.ts +0 -2
  29. package/core/memo.js +1 -3
  30. package/core/mounting.d.ts +7 -9
  31. package/core/mounting.js +221 -82
  32. package/core/patching.d.ts +7 -8
  33. package/core/patching.js +235 -255
  34. package/core/patchingChildren.d.ts +6 -0
  35. package/core/patchingChildren.js +330 -0
  36. package/core/portal.d.ts +1 -1
  37. package/core/portal.js +17 -7
  38. package/core/processStack.d.ts +69 -0
  39. package/core/processStack.js +63 -0
  40. package/core/ref.d.ts +4 -3
  41. package/core/rerender.d.ts +4 -14
  42. package/core/rerender.js +67 -112
  43. package/core/runtime.d.ts +17 -0
  44. package/core/runtime.js +2 -0
  45. package/core/unmounting.d.ts +11 -6
  46. package/core/unmounting.js +81 -40
  47. package/core/utils.d.ts +10 -0
  48. package/core/utils.js +143 -0
  49. package/dom/attach-element-to-dom.d.ts +4 -3
  50. package/dom/attach-element-to-dom.js +12 -7
  51. package/dom/domAdapter.js +22 -25
  52. package/dom/events.d.ts +5 -5
  53. package/dom/events.js +33 -16
  54. package/dom/index.d.ts +16 -5
  55. package/dom/index.js +4 -3
  56. package/dom/props/controlled/index.d.ts +3 -3
  57. package/dom/props/controlled/index.js +8 -8
  58. package/dom/props/controlled/input.d.ts +3 -3
  59. package/dom/props/controlled/input.js +57 -34
  60. package/dom/props/controlled/select.d.ts +3 -3
  61. package/dom/props/controlled/select.js +39 -26
  62. package/dom/props/controlled/textarea.d.ts +3 -3
  63. package/dom/props/controlled/textarea.js +57 -34
  64. package/dom/props/dangerInnerHTML.d.ts +2 -2
  65. package/dom/props/dangerInnerHTML.js +3 -2
  66. package/dom/props/props.d.ts +4 -4
  67. package/dom/props/props.js +24 -21
  68. package/dom/render.d.ts +4 -5
  69. package/dom/render.js +38 -34
  70. package/hooks/index.d.ts +15 -13
  71. package/hooks/index.js +155 -159
  72. package/jsx-runtime/index.d.ts +2 -1
  73. package/package.json +9 -1
  74. package/shared/index.d.ts +10 -0
  75. package/shared/index.js +4 -7
  76. package/shared/utils.js +4 -4
  77. package/shared/EventBus.d.ts +0 -18
  78. 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,11 @@
1
- import type { Many, Maybe } from '../shared/index.js';
2
- 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;
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;
@@ -1,68 +1,109 @@
1
- import { hostAdapter } from './hostAdapter.js';
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
- export function unmount(element) {
5
- if (Array.isArray(element)) {
6
- for (const child of element) {
7
- unmount(child);
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 (element.flag === 'FC') {
12
- // Skip — element is already unmounted.
13
- if (element.unmounted) {
29
+ if ((current.flag & SIMP_ELEMENT_FLAG_FC) !== 0) {
30
+ if (current.unmounted) {
14
31
  return;
15
32
  }
16
- // FC element always has Maybe<SimpElement> due to normalization.
17
- if (element.children) {
18
- unmount(element.children);
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 (element.flag === 'TEXT') {
39
+ if ((current.flag & SIMP_ELEMENT_FLAG_TEXT) !== 0) {
25
40
  return;
26
41
  }
27
- if (element.flag === 'PORTAL') {
28
- remove(element.children, element.ref);
42
+ if ((current.flag & SIMP_ELEMENT_FLAG_PORTAL) !== 0) {
43
+ _remove(current.children, current.ref, frame.meta.renderRuntime);
29
44
  return;
30
45
  }
31
- // Only FRAGMENT and HOST elements remain,
32
- // with Maybe<Many<SimpElement>> children due to normalization.
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 (element.flag === 'HOST') {
37
- unmountRef(element);
38
- hostAdapter.unmountProps(element.reference, element);
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 clearElementHostReference(element, parentHostReference) {
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 === 'HOST' || element.flag === 'TEXT' || element.flag === 'PORTAL') {
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
- if (element.flag === 'FC') {
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 === '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;
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 remove(element, parentReference) {
66
- unmount(element);
67
- clearElementHostReference(element, parentReference);
106
+ export function _remove(element, parentReference, renderRuntime) {
107
+ _clearElementHostReference(element, parentReference, renderRuntime);
108
+ _pushUnmountEnterFrame(element, renderRuntime);
68
109
  }
@@ -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
- 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
  }
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
- domAdapter.insertBefore(parent, child, before);
46
+ parent.insertBefore(child, before);
53
47
  }
54
48
  else {
55
- domAdapter.appendChild(parent, child);
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 { self: 'http://www.w3.org/2000/svg', children: 'http://www.w3.org/2000/svg' };
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 };