Skip to content

Commit 4cb4cf6

Browse files
committed
Merge branch 'build/v2' into v2-merge-main
2 parents bd251be + cb4934b commit 4cb4cf6

21 files changed

+2641
-313
lines changed

.changeset/cyan-bottles-speak.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: creating error overlay

.changeset/dirty-lemons-shop.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: reexecute component with null key

.changeset/fluffy-poets-raise.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: custom event names and DOMContentLoaded handling

.changeset/heavy-kids-wave.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: rendering markdown file with Qwik component

.changeset/tame-glasses-explain.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: inserting new node edge case

packages/docs/src/routes/api/qwik-testing/api.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@
209209
}
210210
],
211211
"kind": "Function",
212-
"content": "Trigger an event in unit tests on an element.\n\nFuture deprecation candidate.\n\n\n```typescript\nexport declare function trigger(root: Element, queryOrElement: string | Element | keyof HTMLElementTagNameMap | null, eventNameCamel: string, eventPayload?: any): Promise<void>;\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nroot\n\n\n</td><td>\n\nElement\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\nqueryOrElement\n\n\n</td><td>\n\nstring \\| Element \\| keyof HTMLElementTagNameMap \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\neventNameCamel\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\neventPayload\n\n\n</td><td>\n\nany\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n</tbody></table>\n**Returns:**\n\nPromise&lt;void&gt;",
212+
"content": "Trigger an event in unit tests on an element.\n\nFuture deprecation candidate.\n\n\n```typescript\nexport declare function trigger(root: Element, queryOrElement: string | Element | keyof HTMLElementTagNameMap | null, eventName: string, eventPayload?: any): Promise<void>;\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nroot\n\n\n</td><td>\n\nElement\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\nqueryOrElement\n\n\n</td><td>\n\nstring \\| Element \\| keyof HTMLElementTagNameMap \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\neventName\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\neventPayload\n\n\n</td><td>\n\nany\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n</tbody></table>\n**Returns:**\n\nPromise&lt;void&gt;",
213213
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/testing/element-fixture.ts",
214214
"mdFile": "core.trigger.md"
215215
},

packages/docs/src/routes/api/qwik-testing/index.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ Future deprecation candidate.
499499
export declare function trigger(
500500
root: Element,
501501
queryOrElement: string | Element | keyof HTMLElementTagNameMap | null,
502-
eventNameCamel: string,
502+
eventName: string,
503503
eventPayload?: any,
504504
): Promise<void>;
505505
```
@@ -541,7 +541,7 @@ string \| Element \| keyof HTMLElementTagNameMap \| null
541541
</td></tr>
542542
<tr><td>
543543

544-
eventNameCamel
544+
eventName
545545

546546
</td><td>
547547

packages/qwik/src/core/client/dom-container.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -200,15 +200,19 @@ export class DomContainer extends _SharedContainer implements IClientContainer {
200200
}
201201
errorDiv.setAttribute('q:key', '_error_');
202202
const journal: VNodeJournal = [];
203-
vnode_getDOMChildNodes(journal, vHost).forEach((child) => errorDiv.appendChild(child));
204-
const vErrorDiv = vnode_newElement(errorDiv, 'error-host');
203+
204+
const vErrorDiv = vnode_newElement(errorDiv, 'errored-host');
205+
206+
vnode_getDOMChildNodes(journal, vHost, true).forEach((child) => {
207+
vnode_insertBefore(journal, vErrorDiv, child, null);
208+
});
205209
vnode_insertBefore(journal, vHost, vErrorDiv, null);
206210
vnode_applyJournal(journal);
207211
}
208212

209213
if (err && err instanceof Error) {
210214
if (!('hostElement' in err)) {
211-
(err as any)['hostElement'] = host;
215+
(err as any)['hostElement'] = String(host);
212216
}
213217
}
214218
if (!isRecoverable(err)) {

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

+11-26
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ import {
3434
import { isPromise } from '../shared/utils/promises';
3535
import { type ValueOrPromise } from '../shared/utils/types';
3636
import {
37-
convertEventNameFromJsxPropToHtmlAttr,
38-
getEventNameFromJsxProp,
39-
getEventNameScopeFromJsxProp,
37+
getEventNameFromJsxEvent,
38+
getEventNameScopeFromJsxEvent,
4039
isHtmlAttributeAnEventName,
4140
isJsxPropertyAnEventName,
41+
jsxEventToHtmlAttribute,
4242
} from '../shared/utils/event-names';
4343
import { ChoreType } from '../shared/util-chore-type';
4444
import { hasClassAttr } from '../shared/utils/scoped-styles';
@@ -491,21 +491,6 @@ export const vnode_diff = (
491491
// All is good.
492492
// console.log(' NOOP', String(vCurrent));
493493
} else {
494-
const parent = vnode_getParent(vProjectedNode);
495-
const isAlreadyProjected =
496-
!!parent && !(vnode_isElementVNode(parent) && vnode_getElementName(parent) === QTemplate);
497-
if (isAlreadyProjected && vParent !== parent) {
498-
/**
499-
* The node is already projected, but structure has been changed. In next steps we will
500-
* insert the vProjectedNode at the end. However we will find existing projection elements
501-
* (from already projected THE SAME projection as vProjectedNode!) during
502-
* vnode_insertBefore. We need to remove vnode from the vnode tree to avoid referencing it
503-
* to self and cause infinite loop. Don't remove it from DOM to avoid additional operations
504-
* and flickering.
505-
*/
506-
vnode_remove(journal, parent, vProjectedNode, false);
507-
}
508-
509494
// move from q:template to the target node
510495
vnode_insertBefore(
511496
journal,
@@ -610,8 +595,8 @@ export const vnode_diff = (
610595
if (isJsxPropertyAnEventName(key)) {
611596
// So for event handlers we must add them to the vNode so that qwikloader can look them up
612597
// But we need to mark them so that they don't get pulled into the diff.
613-
const eventName = getEventNameFromJsxProp(key);
614-
const scope = getEventNameScopeFromJsxProp(key);
598+
const eventName = getEventNameFromJsxEvent(key);
599+
const scope = getEventNameScopeFromJsxEvent(key);
615600
if (eventName) {
616601
vnode_setProp(
617602
vNewNode as ElementVNode,
@@ -625,7 +610,7 @@ export const vnode_diff = (
625610
// add an event attr with empty value for qwikloader element selector.
626611
// We don't need value here. For ssr this value is a QRL,
627612
// but for CSR value should be just empty
628-
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
613+
const htmlEvent = jsxEventToHtmlAttribute(key);
629614
if (htmlEvent) {
630615
vnode_setAttr(journal, vNewNode as ElementVNode, htmlEvent, '');
631616
}
@@ -843,8 +828,8 @@ export const vnode_diff = (
843828
};
844829

845830
const recordJsxEvent = (key: string, value: any) => {
846-
const eventName = getEventNameFromJsxProp(key);
847-
const scope = getEventNameScopeFromJsxProp(key);
831+
const eventName = getEventNameFromJsxEvent(key);
832+
const scope = getEventNameScopeFromJsxEvent(key);
848833
if (eventName) {
849834
record(':' + scope + ':' + eventName, value);
850835
// register an event for qwik loader
@@ -855,7 +840,7 @@ export const vnode_diff = (
855840
// add an event attr with empty value for qwikloader element selector.
856841
// We don't need value here. For ssr this value is a QRL,
857842
// but for CSR value should be just empty
858-
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
843+
const htmlEvent = jsxEventToHtmlAttribute(key);
859844
if (htmlEvent) {
860845
record(htmlEvent, '');
861846
}
@@ -999,7 +984,7 @@ export const vnode_diff = (
999984
}
1000985

1001986
function expectVirtual(type: VirtualType, jsxKey: string | null) {
1002-
if (vCurrent && vnode_isVirtualVNode(vCurrent) && getKey(vCurrent) === jsxKey) {
987+
if (vCurrent && vnode_isVirtualVNode(vCurrent) && getKey(vCurrent) === jsxKey && !!jsxKey) {
1003988
// All is good.
1004989
return;
1005990
} else if (jsxKey !== null) {
@@ -1058,7 +1043,7 @@ export const vnode_diff = (
10581043
}
10591044
host = vNewNode as VirtualVNode;
10601045
shouldRender = true;
1061-
} else if (!hashesAreEqual) {
1046+
} else if (!hashesAreEqual || !jsxNode.key) {
10621047
insertNewComponent(host, componentQRL, jsxProps);
10631048
host = vNewNode as VirtualVNode;
10641049
shouldRender = true;

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

+19-12
Original file line numberDiff line numberDiff line change
@@ -965,11 +965,29 @@ export const vnode_insertBefore = (
965965
if (vnode_isElementVNode(parent)) {
966966
ensureMaterialized(parent);
967967
}
968+
const newChildCurrentParent = newChild[VNodeProps.parent];
968969
if (newChild === insertBefore) {
969970
// invalid insertBefore. We can't insert before self reference
970971
// prevent infinity loop and putting self reference to next sibling
971-
insertBefore = null;
972+
if (newChildCurrentParent) {
973+
// early return, as the newChild is already in the tree and we are already in the correct position
974+
return;
975+
} else {
976+
// if the newChild is not in the tree, than we insert it at the end of the list
977+
insertBefore = null;
978+
}
979+
}
980+
981+
// ensure that the previous node is unlinked.
982+
if (
983+
newChildCurrentParent &&
984+
(newChild[VNodeProps.previousSibling] ||
985+
newChild[VNodeProps.nextSibling] ||
986+
newChildCurrentParent !== parent)
987+
) {
988+
vnode_remove(journal, newChildCurrentParent, newChild, false);
972989
}
990+
973991
let adjustedInsertBefore: VNode | null = null;
974992
if (insertBefore == null) {
975993
if (vnode_isVirtualVNode(parent)) {
@@ -1013,17 +1031,6 @@ export const vnode_insertBefore = (
10131031
);
10141032
}
10151033

1016-
// ensure that the previous node is unlinked.
1017-
const newChildCurrentParent = newChild[VNodeProps.parent];
1018-
if (
1019-
newChildCurrentParent &&
1020-
(newChild[VNodeProps.previousSibling] ||
1021-
newChild[VNodeProps.nextSibling] ||
1022-
(vnode_isElementVNode(newChildCurrentParent) && newChildCurrentParent !== parent))
1023-
) {
1024-
vnode_remove(journal, newChildCurrentParent, newChild, false);
1025-
}
1026-
10271034
// link newChild into the previous/next list
10281035
const vNext = insertBefore;
10291036
const vPrevious = vNext

0 commit comments

Comments
 (0)