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