@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/patching.js CHANGED
@@ -1,82 +1,156 @@
1
- import { emptyObject } from '../shared/index.js';
2
- import { normalizeRoot } from './createElement.js';
3
- import { hostAdapter } from './hostAdapter.js';
4
- import { clearElementHostReference, remove, unmount } from './unmounting.js';
5
- import { mount, mountArrayChildren, mountFunctionalElement } from './mounting.js';
6
- import { applyRef } from './ref.js';
1
+ import { normalizeRoot, SIMP_ELEMENT_CHILD_FLAG_ELEMENT, SIMP_ELEMENT_CHILD_FLAG_EMPTY, SIMP_ELEMENT_CHILD_FLAG_LIST, SIMP_ELEMENT_FLAG_HOST, } from './createElement.js';
2
+ import { _pushHostOperationReplaceElement } from './hostOperations.js';
7
3
  import { lifecycleEventBus } from './lifecycleEventBus.js';
8
- import { batchingRerenderLocker } from './rerender.js';
9
4
  import { isMemo } from './memo.js';
10
- export function patch(prevElement, nextElement, parentReference, nextReference, context, hostNamespace) {
5
+ import { _pushMountEnterFrame } from './mounting.js';
6
+ import { _pushPatchChildrenFrame } from './patchingChildren.js';
7
+ import { PATCH_ENTER, PATCH_EXIT, processStack } from './processStack.js';
8
+ import { applyRef } from './ref.js';
9
+ import { UPDATING_PHASE } from './runtime.js';
10
+ import { _clearElementHostReference, _pushUnmountEnterFrame, _remove } from './unmounting.js';
11
+ import { bitScanForwardIndex } from './utils.js';
12
+ const patchHandlers = [_patchHostElement, _patchFunctionalComponent, _patchTextElement, _patchPortal, _patchFragment];
13
+ export function patch(prevElement, nextElement, parentReference, rightSibling, context, hostNamespace, renderRuntime) {
14
+ if (renderRuntime.renderStack.length !== 0) {
15
+ throw new Error('Cannot patch while rendering.');
16
+ }
17
+ _pushPatchEnterFrame(nextElement, {
18
+ prevElement,
19
+ parentReference,
20
+ renderRuntime,
21
+ rightSibling,
22
+ context,
23
+ hostNamespace,
24
+ placeHolderElement: null,
25
+ });
26
+ processStack(renderRuntime);
27
+ }
28
+ export function _pushPatchEnterFrame(element, meta) {
29
+ meta.renderRuntime.renderStack.push({
30
+ node: element,
31
+ kind: PATCH_ENTER,
32
+ meta,
33
+ });
34
+ }
35
+ export function _pushPatchExitFrame(element, meta) {
36
+ meta.renderRuntime.renderStack.push({
37
+ node: element,
38
+ kind: PATCH_EXIT,
39
+ meta,
40
+ });
41
+ }
42
+ export function _patch(frame) {
43
+ const nextElement = frame.node;
44
+ const { prevElement } = frame.meta;
45
+ // Early return if the elements are different type or have different keys.
11
46
  if (prevElement.type !== nextElement.type || prevElement.key !== nextElement.key) {
12
- replaceWithNewElement(prevElement, nextElement, parentReference, context, hostNamespace);
13
- }
14
- else if (nextElement.flag === 'HOST') {
15
- patchHostElement(prevElement, nextElement, context, hostNamespace);
16
- }
17
- else if (nextElement.flag === 'FC') {
18
- patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, context, hostNamespace);
19
- }
20
- else if (nextElement.flag === 'TEXT') {
21
- patchTextElement(prevElement, nextElement);
22
- }
23
- else if (nextElement.flag === 'FRAGMENT') {
24
- patchFragment(prevElement, nextElement, parentReference, context, hostNamespace);
25
- }
26
- else {
27
- patchPortal(prevElement, nextElement, context);
47
+ _replaceWithNewElement(frame);
48
+ return;
28
49
  }
50
+ patchHandlers[bitScanForwardIndex(frame.node.flag)](frame);
29
51
  }
30
- function replaceWithNewElement(prevElement, nextElement, parentReference, context, hostNamespace) {
31
- unmount(prevElement);
52
+ function _replaceWithNewElement(frame) {
53
+ const nextElement = frame.node;
54
+ const { prevElement, parentReference, context, hostNamespace, renderRuntime } = frame.meta;
55
+ _pushUnmountEnterFrame(prevElement, renderRuntime);
32
56
  nextElement.parent = prevElement.parent;
33
- if (nextElement.flag === 'HOST' && prevElement.flag === 'HOST') {
34
- mount(nextElement, null, null, context, hostNamespace);
35
- hostAdapter.replaceChild(parentReference, nextElement.reference, prevElement.reference);
57
+ if ((nextElement.flag & SIMP_ELEMENT_FLAG_HOST) !== 0 && (prevElement.flag & SIMP_ELEMENT_FLAG_HOST) !== 0) {
58
+ _pushHostOperationReplaceElement(nextElement, renderRuntime, {
59
+ prevElement,
60
+ parentReference,
61
+ });
62
+ _pushMountEnterFrame(nextElement, {
63
+ context,
64
+ hostNamespace,
65
+ renderRuntime,
66
+ parentReference: null,
67
+ rightSibling: null,
68
+ placeHolderElement: null,
69
+ });
36
70
  }
37
71
  else {
38
- mount(nextElement, parentReference, findHostReferenceFromElement(prevElement), context, hostNamespace);
39
- clearElementHostReference(prevElement, parentReference);
72
+ _clearElementHostReference(prevElement, parentReference, renderRuntime);
73
+ _pushMountEnterFrame(nextElement, {
74
+ rightSibling: frame.meta.rightSibling,
75
+ renderRuntime,
76
+ hostNamespace,
77
+ context,
78
+ parentReference,
79
+ placeHolderElement: null,
80
+ });
40
81
  }
41
82
  }
42
- function patchHostElement(prevElement, nextElement, context, hostNamespace) {
43
- if (prevElement.ref) {
44
- nextElement.ref = prevElement.ref;
83
+ function _patchHostElement(frame) {
84
+ const nextElement = frame.node;
85
+ const { prevElement, context, hostNamespace, renderRuntime } = frame.meta;
86
+ if (frame.kind === PATCH_EXIT) {
87
+ renderRuntime.hostAdapter.patchProps(nextElement.reference, prevElement, nextElement, renderRuntime, hostNamespace);
88
+ if (prevElement.className !== nextElement.className) {
89
+ renderRuntime.hostAdapter.setClassname(nextElement.reference, nextElement.className, hostNamespace);
90
+ }
91
+ applyRef(nextElement);
92
+ return;
45
93
  }
46
- const hostNamespaces = hostAdapter.getHostNamespaces(nextElement, hostNamespace);
47
- hostNamespace = hostNamespaces?.self;
94
+ nextElement.ref = prevElement.ref;
48
95
  nextElement.reference = prevElement.reference;
49
- hostAdapter.attachElementToReference(nextElement, nextElement.reference);
50
- patchChildren(prevElement.children || prevElement.props?.children, nextElement.children || nextElement.props?.children, nextElement.reference, null, nextElement, context, hostNamespaces?.children);
51
- hostAdapter.patchProps(nextElement.reference, prevElement, nextElement, hostNamespace);
52
- if (prevElement.className !== nextElement.className) {
53
- hostAdapter.setClassname(nextElement.reference, nextElement.className, hostNamespace);
54
- }
55
- applyRef(nextElement);
96
+ renderRuntime.hostAdapter.attachElementToReference(nextElement, nextElement.reference, renderRuntime);
97
+ _pushPatchExitFrame(nextElement, {
98
+ prevElement,
99
+ renderRuntime,
100
+ hostNamespace,
101
+ rightSibling: null,
102
+ context: null,
103
+ parentReference: null,
104
+ placeHolderElement: null,
105
+ });
106
+ _pushPatchChildrenFrame(nextElement, {
107
+ prevElement,
108
+ renderRuntime,
109
+ hostNamespace: renderRuntime.hostAdapter.getHostNamespaces(nextElement, hostNamespace)?.children,
110
+ rightSibling: null,
111
+ context,
112
+ parentReference: nextElement.reference,
113
+ placeHolderElement: null,
114
+ });
56
115
  }
57
- function patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, context, hostNamespace) {
58
- nextElement.store = prevElement.store || {};
59
- nextElement.store.latestElement = nextElement;
60
- if (hostNamespace) {
61
- nextElement.store.hostNamespace = hostNamespace;
62
- }
63
- let forceRender = false;
64
- if (prevElement.store?.forceRender) {
65
- forceRender = true;
66
- prevElement.store.forceRender = false;
116
+ function _patchFunctionalComponent(frame) {
117
+ const nextElement = frame.node;
118
+ const { prevElement, context, renderRuntime, hostNamespace, rightSibling, parentReference } = frame.meta;
119
+ if (frame.kind === PATCH_EXIT) {
120
+ lifecycleEventBus.publish({ type: 'updated', element: nextElement, renderRuntime });
121
+ return;
67
122
  }
68
123
  if (prevElement.unmounted) {
69
- mountFunctionalElement(nextElement, parentReference, nextReference, context, hostNamespace);
124
+ _pushMountEnterFrame(nextElement, {
125
+ rightSibling,
126
+ renderRuntime,
127
+ hostNamespace,
128
+ context,
129
+ parentReference,
130
+ placeHolderElement: null,
131
+ });
70
132
  return;
71
133
  }
72
- if (!forceRender && isMemo(nextElement.type) && nextElement.type._compare(prevElement.props, nextElement.props)) {
134
+ nextElement.store = prevElement.store;
135
+ nextElement.store.latestElement = nextElement;
136
+ if (hostNamespace) {
137
+ nextElement.store.hostNamespace = hostNamespace;
138
+ }
139
+ if (isMemo(nextElement.type) &&
140
+ !nextElement.store.forceRerender &&
141
+ nextElement.type._compare(prevElement.props, nextElement.props)) {
142
+ nextElement.childFlag = prevElement.childFlag;
143
+ nextElement.children = prevElement.children;
144
+ nextElement.context = prevElement.context;
73
145
  return;
74
146
  }
75
147
  nextElement.context = prevElement.context || context;
76
- // FC element always has Maybe<SimpElement> children due to normalization process.
148
+ const prevElementSnapshot = prevElement === nextElement ? { ...prevElement } : prevElement;
77
149
  let nextChildren;
78
150
  let triedToRerenderUnsubscribe;
79
151
  try {
152
+ renderRuntime.renderPhase = UPDATING_PHASE;
153
+ renderRuntime.currentRenderingFCElement = nextElement;
80
154
  let triedToRerender = false;
81
155
  let rerenderCounter = 0;
82
156
  triedToRerenderUnsubscribe = lifecycleEventBus.subscribe(event => {
@@ -89,222 +163,128 @@ function patchFunctionalComponent(prevElement, nextElement, parentReference, nex
89
163
  if (++rerenderCounter >= 25) {
90
164
  throw new Error('Too many re-renders.');
91
165
  }
92
- lifecycleEventBus.publish({ type: 'beforeRender', element: nextElement, phase: 'updating' });
93
- batchingRerenderLocker.lock();
94
- nextChildren = nextElement.type(nextElement.props || emptyObject);
95
- batchingRerenderLocker.flush();
96
- lifecycleEventBus.publish({ type: 'afterRender', element: nextElement, phase: 'updating' });
166
+ lifecycleEventBus.publish({
167
+ type: 'beforeRender',
168
+ element: nextElement,
169
+ renderRuntime,
170
+ });
171
+ nextChildren = renderRuntime.renderer(nextElement.type, nextElement, renderRuntime);
172
+ lifecycleEventBus.publish({
173
+ type: 'afterRender',
174
+ element: nextElement,
175
+ renderRuntime,
176
+ });
97
177
  } while (triedToRerender);
98
- nextChildren = normalizeRoot(nextChildren, false);
178
+ normalizeRoot(nextElement, nextChildren, false);
99
179
  }
100
180
  catch (error) {
101
- lifecycleEventBus.publish({ type: 'errored', element: nextElement, error, phase: 'updating' });
102
- remove(prevElement, parentReference);
181
+ const parentChildren = prevElement.parent?.children;
182
+ if (prevElement.parent?.childFlag === SIMP_ELEMENT_CHILD_FLAG_LIST) {
183
+ const parentChildrenList = parentChildren;
184
+ parentChildrenList.splice(prevElement.index, 1);
185
+ if (parentChildrenList.length === 1) {
186
+ prevElement.parent.children = parentChildrenList[0];
187
+ prevElement.parent.childFlag = SIMP_ELEMENT_CHILD_FLAG_ELEMENT;
188
+ }
189
+ else {
190
+ for (let i = prevElement.index; i < parentChildrenList.length; i++) {
191
+ parentChildrenList[i].index = i;
192
+ }
193
+ }
194
+ }
195
+ else if (prevElement.parent) {
196
+ prevElement.parent.childFlag = SIMP_ELEMENT_CHILD_FLAG_EMPTY;
197
+ prevElement.parent.children = null;
198
+ }
199
+ _remove(prevElement, parentReference, renderRuntime);
200
+ const event = {
201
+ type: 'errored',
202
+ element: nextElement,
203
+ error,
204
+ handled: false,
205
+ renderRuntime,
206
+ };
207
+ lifecycleEventBus.publish(event);
208
+ if (!event.handled) {
209
+ throw new Error('Error occurred during rendering a component', { cause: event.error });
210
+ }
103
211
  return;
104
212
  }
105
213
  finally {
106
214
  triedToRerenderUnsubscribe();
107
- }
108
- // Keep prevElement's children reference when prev and next elements are identical to avoid reassignment.
109
- const prevChildren = prevElement.children;
110
- if (nextChildren) {
111
- nextElement.children = nextChildren;
112
- }
113
- patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, nextElement.context, hostNamespace);
114
- lifecycleEventBus.publish({ type: 'updated', element: nextElement });
215
+ renderRuntime.renderPhase = null;
216
+ renderRuntime.currentRenderingFCElement = null;
217
+ }
218
+ _pushPatchExitFrame(nextElement, {
219
+ prevElement,
220
+ renderRuntime,
221
+ hostNamespace,
222
+ rightSibling: null,
223
+ context: null,
224
+ parentReference: null,
225
+ placeHolderElement: null,
226
+ });
227
+ _pushPatchChildrenFrame(nextElement, {
228
+ prevElement: prevElementSnapshot,
229
+ renderRuntime,
230
+ hostNamespace,
231
+ rightSibling,
232
+ context,
233
+ parentReference,
234
+ placeHolderElement: null,
235
+ });
115
236
  }
116
- function patchTextElement(prevElement, nextElement) {
237
+ function _patchTextElement(frame) {
238
+ const nextElement = frame.node;
239
+ const { prevElement, renderRuntime } = frame.meta;
117
240
  nextElement.reference = prevElement.reference;
118
241
  if (nextElement.children !== prevElement.children) {
119
- hostAdapter.setTextContent(nextElement.reference, nextElement.children);
120
- }
121
- }
122
- function patchFragment(prevElement, nextElement, parentReference, context, hostNamespace) {
123
- let nextReference = null;
124
- if (Array.isArray(prevElement.children) && !Array.isArray(nextElement.children) && nextElement.children) {
125
- nextReference = hostAdapter.findNextSiblingReference(findHostReferenceFromElement(prevElement.children[prevElement.children.length - 1]));
242
+ renderRuntime.hostAdapter.setTextContent(nextElement.reference, nextElement.children);
126
243
  }
127
- patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, context, hostNamespace);
128
244
  }
129
- export function patchPortal(prevElement, nextElement, context) {
245
+ function _patchPortal(frame) {
246
+ const nextElement = frame.node;
247
+ const { prevElement, renderRuntime, context } = frame.meta;
130
248
  const prevContainer = prevElement.ref;
131
249
  const nextContainer = nextElement.ref;
132
250
  const nextChildren = nextElement.children;
133
- patchChildren(prevElement.children, nextChildren, prevContainer, null, nextElement, context, hostAdapter.getHostNamespaces(nextChildren, undefined)?.self);
251
+ if (frame.kind === PATCH_EXIT) {
252
+ renderRuntime.hostAdapter.removeChild(prevContainer, nextChildren.reference);
253
+ renderRuntime.hostAdapter.insertOrAppend(nextContainer, nextChildren.reference, null);
254
+ return;
255
+ }
134
256
  nextElement.reference = prevElement.reference;
135
257
  if (prevContainer !== nextContainer && nextChildren != null) {
136
- hostAdapter.removeChild(prevContainer, nextChildren.reference);
137
- hostAdapter.appendChild(nextContainer, nextChildren.reference);
138
- }
139
- }
140
- export function updateFunctionalComponent(element, parentReference, nextReference, context, hostNamespace) {
141
- patchFunctionalComponent(element, element, parentReference, nextReference, context, hostNamespace);
142
- }
143
- function patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, context, hostNamespace) {
144
- if (Array.isArray(prevChildren)) {
145
- if (Array.isArray(nextChildren)) {
146
- for (const child of nextChildren) {
147
- child.parent = nextElement;
148
- }
149
- patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace);
150
- }
151
- else if (typeof nextChildren === 'string') {
152
- unmount(prevChildren);
153
- hostAdapter.setTextContent(parentReference, nextChildren);
154
- }
155
- else if (nextChildren) {
156
- patchKeyedChildren(prevChildren, [nextChildren], parentReference, nextReference, context, hostNamespace);
157
- }
158
- else {
159
- unmount(prevChildren);
160
- hostAdapter.clearNode(parentReference);
161
- }
162
- }
163
- else if (typeof prevChildren === 'string') {
164
- if (Array.isArray(nextChildren)) {
165
- hostAdapter.clearNode(parentReference);
166
- mountArrayChildren(nextChildren, parentReference, nextReference, context, nextElement, hostNamespace);
167
- }
168
- else if (typeof nextChildren === 'string') {
169
- if (prevChildren !== nextChildren) {
170
- hostAdapter.setTextContent(nextElement.reference, nextChildren, true);
171
- }
172
- }
173
- else if (nextChildren) {
174
- hostAdapter.clearNode(parentReference);
175
- nextChildren.parent = nextElement;
176
- mount(nextChildren, parentReference, nextReference, context, hostNamespace);
177
- }
178
- else {
179
- hostAdapter.clearNode(parentReference);
180
- }
181
- }
182
- else if (prevChildren) {
183
- if (Array.isArray(nextChildren)) {
184
- patchKeyedChildren([prevChildren], nextChildren, parentReference, nextReference, context, hostNamespace);
185
- }
186
- else if (typeof nextChildren === 'string') {
187
- unmount(prevChildren);
188
- hostAdapter.setTextContent(parentReference, nextChildren);
189
- }
190
- else if (nextChildren) {
191
- nextChildren.parent = nextElement;
192
- patch(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace);
193
- }
194
- else {
195
- remove(prevChildren, parentReference);
196
- }
197
- }
198
- else {
199
- if (Array.isArray(nextChildren)) {
200
- mountArrayChildren(nextChildren, parentReference, nextReference, context, nextElement, hostNamespace);
201
- }
202
- else if (typeof nextChildren === 'string') {
203
- hostAdapter.setTextContent(parentReference, nextChildren);
204
- }
205
- else if (nextChildren) {
206
- nextChildren.parent = nextElement;
207
- mount(nextChildren, parentReference, nextReference, context, hostNamespace);
208
- }
209
- }
210
- }
211
- export function patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace) {
212
- let prevStart = 0;
213
- let nextStart = 0;
214
- let prevEnd = prevChildren.length - 1;
215
- let nextEnd = nextChildren.length - 1;
216
- // Step 1: Sync from start
217
- while (prevStart <= prevEnd &&
218
- nextStart <= nextEnd &&
219
- prevChildren[prevStart].key === nextChildren[nextStart].key) {
220
- patch(prevChildren[prevStart], nextChildren[nextStart], parentReference, null, context, hostNamespace);
221
- prevStart++;
222
- nextStart++;
223
- }
224
- // Step 2: Sync from end
225
- while (prevStart <= prevEnd && nextStart <= nextEnd && prevChildren[prevEnd].key === nextChildren[nextEnd].key) {
226
- patch(prevChildren[prevEnd], nextChildren[nextEnd], parentReference, null, context, hostNamespace);
227
- prevEnd--;
228
- nextEnd--;
229
- }
230
- // Step 3: Mount new nodes if prev list is exhausted
231
- if (prevStart > prevEnd) {
232
- const before = findHostReferenceFromElement(nextChildren[nextEnd + 1]) || nextReference;
233
- for (let i = nextStart; i <= nextEnd; i++) {
234
- mount(nextChildren[i], parentReference, before, context, hostNamespace);
235
- }
236
- // Step 4: Remove prev nodes if next list is exhausted
237
- }
238
- else if (nextStart > nextEnd) {
239
- for (let i = prevStart; i <= prevEnd; i++) {
240
- remove(prevChildren[i], parentReference);
241
- }
242
- }
243
- // Step 5: Full diff with keyed lookup and movement
244
- else {
245
- // Create map of keys to indices for prev children
246
- const keyToPrevIndexMap = new Map();
247
- for (let i = prevStart; i <= prevEnd; i++) {
248
- const key = prevChildren[i].key;
249
- if (key != null) {
250
- keyToPrevIndexMap.set(key, i);
251
- }
252
- }
253
- // Track reused indices and move plan
254
- const toMove = new Array(nextEnd - nextStart + 1);
255
- const usedIndices = new Set();
256
- // Match and patch/mount
257
- for (let i = nextStart; i <= nextEnd; i++) {
258
- const nextChild = nextChildren[i];
259
- const prevIndex = keyToPrevIndexMap.get(nextChild.key);
260
- if (prevIndex != null) {
261
- const prevElement = prevChildren[prevIndex];
262
- patch(prevElement, nextChild, parentReference, null, context, hostNamespace);
263
- toMove[i - nextStart] = prevIndex;
264
- usedIndices.add(prevIndex);
265
- }
266
- else {
267
- mount(nextChild, parentReference, findHostReferenceFromElement(nextChildren[i + 1]) || nextReference, context, hostNamespace);
268
- toMove[i - nextStart] = -1;
269
- }
270
- }
271
- // Remove nodes not matched
272
- for (let i = prevStart; i <= prevEnd; i++) {
273
- if (!usedIndices.has(i)) {
274
- remove(prevChildren[i], parentReference);
275
- }
276
- }
277
- // Insert in correct order
278
- for (let i = nextEnd; i >= nextStart; i--) {
279
- const currentChild = nextChildren[i];
280
- const reference = findHostReferenceFromElement(nextChildren[i + 1]) || nextReference;
281
- if (toMove[i - nextStart] !== -1) {
282
- hostAdapter.insertBefore(parentReference, currentChild.reference, reference);
283
- }
284
- }
285
- }
286
- }
287
- export function findParentReferenceFromElement(element) {
288
- let flag;
289
- let temp = element;
290
- while (temp != null) {
291
- flag = temp.flag;
292
- if (flag === 'HOST') {
293
- return temp.reference;
294
- }
295
- temp = temp.parent;
258
+ _pushPatchExitFrame(nextElement, {
259
+ prevElement,
260
+ renderRuntime,
261
+ hostNamespace: null,
262
+ rightSibling: null,
263
+ context: null,
264
+ parentReference: null,
265
+ placeHolderElement: null,
266
+ });
296
267
  }
297
- return null;
268
+ _pushPatchChildrenFrame(nextElement, {
269
+ prevElement,
270
+ renderRuntime,
271
+ hostNamespace: renderRuntime.hostAdapter.getHostNamespaces(nextChildren, undefined)?.self,
272
+ rightSibling: null,
273
+ context,
274
+ parentReference: nextContainer,
275
+ placeHolderElement: null,
276
+ });
298
277
  }
299
- export function findHostReferenceFromElement(element) {
300
- let flag;
301
- let temp = element;
302
- while (temp != null) {
303
- flag = temp.flag;
304
- if (flag === 'HOST' || flag === 'TEXT' || flag === 'PORTAL') {
305
- return temp.reference;
306
- }
307
- temp = (Array.isArray(temp.children) ? temp.children[0] : temp.children);
308
- }
309
- return null;
278
+ function _patchFragment(frame) {
279
+ const nextElement = frame.node;
280
+ const { prevElement, renderRuntime, context, parentReference, hostNamespace, rightSibling } = frame.meta;
281
+ _pushPatchChildrenFrame(nextElement, {
282
+ prevElement,
283
+ parentReference,
284
+ rightSibling,
285
+ context,
286
+ renderRuntime,
287
+ hostNamespace,
288
+ placeHolderElement: null,
289
+ });
310
290
  }
@@ -0,0 +1,6 @@
1
+ import { type SimpElement } from './createElement.js';
2
+ import { type PatchChildrenFrame, type PatchFrameMeta } from './processStack.js';
3
+ export declare function _pushPatchChildrenFrame(element: SimpElement, meta: PatchFrameMeta): void;
4
+ export declare function _pushPatchKeyedChildrenFrame(element: SimpElement, meta: PatchFrameMeta): void;
5
+ export declare function _patchChildren(frame: PatchChildrenFrame): void;
6
+ export declare function _patchKeyedChildren(frame: PatchChildrenFrame): void;