Skip to content

Commit e829326

Browse files
committed
fix: removing text node from shared text node
1 parent a8f0942 commit e829326

File tree

3 files changed

+190
-10
lines changed

3 files changed

+190
-10
lines changed

.changeset/wicked-pets-chew.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: removing text node from shared text node

packages/qwik/src/core/client/vnode.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,17 @@ export const vnode_remove = (
10671067
vnode_ensureTextInflated(journal, vToRemove);
10681068
}
10691069

1070+
if (removeDOM) {
1071+
const domParent = vnode_getDomParent(vParent);
1072+
const isInnerHTMLParent = vnode_getAttr(vParent, dangerouslySetInnerHTML);
1073+
if (isInnerHTMLParent) {
1074+
// ignore children, as they are inserted via innerHTML
1075+
return;
1076+
}
1077+
const children = vnode_getDOMChildNodes(journal, vToRemove);
1078+
domParent && children.length && journal.push(VNodeJournalOpCode.Remove, domParent, ...children);
1079+
}
1080+
10701081
const vPrevious = vToRemove[VNodeProps.previousSibling];
10711082
const vNext = vToRemove[VNodeProps.nextSibling];
10721083
if (vPrevious) {
@@ -1081,16 +1092,6 @@ export const vnode_remove = (
10811092
}
10821093
vToRemove[VNodeProps.previousSibling] = null;
10831094
vToRemove[VNodeProps.nextSibling] = null;
1084-
if (removeDOM) {
1085-
const domParent = vnode_getDomParent(vParent);
1086-
const isInnerHTMLParent = vnode_getAttr(vParent, dangerouslySetInnerHTML);
1087-
if (isInnerHTMLParent) {
1088-
// ignore children, as they are inserted via innerHTML
1089-
return;
1090-
}
1091-
const children = vnode_getDOMChildNodes(journal, vToRemove);
1092-
domParent && children.length && journal.push(VNodeJournalOpCode.Remove, domParent, ...children);
1093-
}
10941095
};
10951096

10961097
export const vnode_queryDomNodes = (

packages/qwik/src/core/client/vnode.unit.tsx

+174
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,180 @@ describe('vnode', () => {
227227
vnode_applyJournal(journal);
228228
expect(parent.innerHTML).toEqual(`AB`);
229229
});
230+
231+
describe('node removing from shared text node', () => {
232+
it('should inflate text nodes on first node remove', () => {
233+
parent.innerHTML = `012`;
234+
document.qVNodeData.set(parent, 'BBB');
235+
vnode_getFirstChild(vParent) as VirtualVNode;
236+
expect(vParent).toMatchVDOM(
237+
<test>
238+
{'0'}
239+
{'1'}
240+
{'2'}
241+
</test>
242+
);
243+
const firstText = vnode_getFirstChild(vParent) as TextVNode;
244+
vnode_remove(journal, vParent, firstText, true);
245+
vnode_applyJournal(journal);
246+
expect(vParent).toMatchVDOM(
247+
<test>
248+
{'1'}
249+
{'2'}
250+
</test>
251+
);
252+
expect(parent.innerHTML).toEqual(`12`);
253+
});
254+
255+
it('should inflate text nodes on second node remove', () => {
256+
parent.innerHTML = `012`;
257+
document.qVNodeData.set(parent, 'BBB');
258+
vnode_getFirstChild(vParent) as VirtualVNode;
259+
expect(vParent).toMatchVDOM(
260+
<test>
261+
{'0'}
262+
{'1'}
263+
{'2'}
264+
</test>
265+
);
266+
const firstText = vnode_getFirstChild(vParent) as TextVNode;
267+
const secondText = vnode_getNextSibling(firstText) as TextVNode;
268+
vnode_remove(journal, vParent, secondText, true);
269+
vnode_applyJournal(journal);
270+
expect(vParent).toMatchVDOM(
271+
<test>
272+
{'0'}
273+
{'2'}
274+
</test>
275+
);
276+
expect(parent.innerHTML).toEqual(`02`);
277+
});
278+
279+
it('should inflate text nodes on last node remove', () => {
280+
parent.innerHTML = `012`;
281+
document.qVNodeData.set(parent, 'BBB');
282+
vnode_getFirstChild(vParent) as VirtualVNode;
283+
expect(vParent).toMatchVDOM(
284+
<test>
285+
{'0'}
286+
{'1'}
287+
{'2'}
288+
</test>
289+
);
290+
const firstText = vnode_getFirstChild(vParent) as TextVNode;
291+
const secondText = vnode_getNextSibling(firstText) as TextVNode;
292+
const thirdText = vnode_getNextSibling(secondText) as TextVNode;
293+
vnode_remove(journal, vParent, thirdText, true);
294+
vnode_applyJournal(journal);
295+
expect(vParent).toMatchVDOM(
296+
<test>
297+
{'0'}
298+
{'1'}
299+
</test>
300+
);
301+
expect(parent.innerHTML).toEqual(`01`);
302+
});
303+
304+
it('should inflate text nodes on first node remove and change text of second', () => {
305+
parent.innerHTML = `012`;
306+
document.qVNodeData.set(parent, 'BBB');
307+
vnode_getFirstChild(vParent) as VirtualVNode;
308+
expect(vParent).toMatchVDOM(
309+
<test>
310+
{'0'}
311+
{'1'}
312+
{'2'}
313+
</test>
314+
);
315+
const firstText = vnode_getFirstChild(vParent) as TextVNode;
316+
const secondText = vnode_getNextSibling(firstText) as TextVNode;
317+
vnode_remove(journal, vParent, firstText, true);
318+
vnode_setText(journal, secondText, '!');
319+
vnode_applyJournal(journal);
320+
expect(vParent).toMatchVDOM(
321+
<test>
322+
{'!'}
323+
{'2'}
324+
</test>
325+
);
326+
expect(parent.innerHTML).toEqual(`!2`);
327+
});
328+
329+
it('should inflate text nodes on first virtual node remove', () => {
330+
parent.innerHTML = `0123`;
331+
document.qVNodeData.set(parent, '{B}{B}{B}');
332+
vnode_getFirstChild(vParent) as VirtualVNode;
333+
expect(vParent).toMatchVDOM(
334+
<test>
335+
<>0</>
336+
<>1</>
337+
<>2</>
338+
</test>
339+
);
340+
const firstVirtual = vnode_getFirstChild(vParent) as VirtualVNode;
341+
vnode_remove(journal, vParent, firstVirtual, true);
342+
343+
vnode_applyJournal(journal);
344+
expect(vParent).toMatchVDOM(
345+
<test>
346+
<>1</>
347+
<>2</>
348+
</test>
349+
);
350+
expect(parent.innerHTML).toEqual(`12`);
351+
});
352+
353+
it('should inflate text nodes on middle virtual node remove', () => {
354+
parent.innerHTML = `0123`;
355+
document.qVNodeData.set(parent, '{B}{B}{B}');
356+
vnode_getFirstChild(vParent) as VirtualVNode;
357+
expect(vParent).toMatchVDOM(
358+
<test>
359+
<>0</>
360+
<>1</>
361+
<>2</>
362+
</test>
363+
);
364+
const firstVirtual = vnode_getFirstChild(vParent) as VirtualVNode;
365+
const secondVirtual = vnode_getNextSibling(firstVirtual) as VirtualVNode;
366+
vnode_remove(journal, vParent, secondVirtual, true);
367+
368+
vnode_applyJournal(journal);
369+
expect(vParent).toMatchVDOM(
370+
<test>
371+
<>0</>
372+
<>2</>
373+
</test>
374+
);
375+
expect(parent.innerHTML).toEqual(`02`);
376+
});
377+
378+
it('should inflate text nodes on last virtual node remove', () => {
379+
parent.innerHTML = `0123`;
380+
document.qVNodeData.set(parent, '{B}{B}{B}');
381+
vnode_getFirstChild(vParent) as VirtualVNode;
382+
expect(vParent).toMatchVDOM(
383+
<test>
384+
<>0</>
385+
<>1</>
386+
<>2</>
387+
</test>
388+
);
389+
const firstVirtual = vnode_getFirstChild(vParent) as VirtualVNode;
390+
const secondVirtual = vnode_getNextSibling(firstVirtual) as VirtualVNode;
391+
const thirdVirtual = vnode_getNextSibling(secondVirtual) as VirtualVNode;
392+
vnode_remove(journal, vParent, thirdVirtual, true);
393+
394+
vnode_applyJournal(journal);
395+
expect(vParent).toMatchVDOM(
396+
<test>
397+
<>0</>
398+
<>1</>
399+
</test>
400+
);
401+
expect(parent.innerHTML).toEqual(`01`);
402+
});
403+
});
230404
});
231405
describe('virtual', () => {
232406
it('should create empty Virtual', () => {

0 commit comments

Comments
 (0)