Skip to content

Commit 8fa44f3

Browse files
committed
fix: handling spread props on element node
1 parent 151849a commit 8fa44f3

14 files changed

+318
-34
lines changed

.changeset/plain-eggs-clean.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: handling spread props on element node

packages/qwik/src/core/tests/attributes.spec.tsx

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,200 @@ describe.each([
533533
);
534534
});
535535

536+
describe('spread props', () => {
537+
describe('class attribute from component props', () => {
538+
it('should use class attribute from element', async () => {
539+
const Cmp = component$((props: PropsOf<'div'>) => {
540+
return <div {...props} class={[props.class, 'component']} />;
541+
});
542+
543+
const Parent = component$(() => {
544+
return <Cmp class="test" />;
545+
});
546+
547+
const { vNode } = await render(<Parent />, { debug });
548+
expect(vNode).toMatchVDOM(
549+
<Component>
550+
<Component>
551+
<div class="test component"></div>
552+
</Component>
553+
</Component>
554+
);
555+
});
556+
557+
it('should use class attribute from props', async () => {
558+
const Cmp = component$((props: PropsOf<'div'>) => {
559+
return <div class={[props.class, 'component']} {...props} />;
560+
});
561+
562+
const Parent = component$(() => {
563+
return <Cmp class="test" />;
564+
});
565+
566+
const { vNode } = await render(<Parent />, { debug });
567+
expect(vNode).toMatchVDOM(
568+
<Component>
569+
<Component>
570+
<div class="test"></div>
571+
</Component>
572+
</Component>
573+
);
574+
});
575+
});
576+
577+
describe('class attribute without component props', () => {
578+
it('should use class attribute from props', async () => {
579+
const Cmp = component$((props: PropsOf<'div'>) => {
580+
return <div class="test component" {...props} />;
581+
});
582+
583+
const Parent = component$(() => {
584+
return <Cmp class="test" />;
585+
});
586+
587+
const { vNode } = await render(<Parent />, { debug });
588+
expect(vNode).toMatchVDOM(
589+
<Component>
590+
<Component>
591+
<div class="test"></div>
592+
</Component>
593+
</Component>
594+
);
595+
});
596+
597+
it('should use class attribute from element', async () => {
598+
const Cmp = component$((props: PropsOf<'div'>) => {
599+
return <div {...props} class="test component" />;
600+
});
601+
602+
const Parent = component$(() => {
603+
return <Cmp class="test" />;
604+
});
605+
606+
const { vNode } = await render(<Parent />, { debug });
607+
expect(vNode).toMatchVDOM(
608+
<Component>
609+
<Component>
610+
<div class="test component"></div>
611+
</Component>
612+
</Component>
613+
);
614+
});
615+
});
616+
617+
it('should handle multiple spread component props', async () => {
618+
const Cmp = component$((props: PropsOf<'div'>) => {
619+
return <div {...props} class="test component" {...props} />;
620+
});
621+
622+
const Parent = component$(() => {
623+
return <Cmp class="test" />;
624+
});
625+
626+
const { vNode } = await render(<Parent />, { debug });
627+
628+
expect(vNode).toMatchVDOM(
629+
<Component>
630+
<Component>
631+
<div class="test"></div>
632+
</Component>
633+
</Component>
634+
);
635+
});
636+
637+
it('should handle multiple spread component and element props', async () => {
638+
const Cmp = component$((props: PropsOf<'div'>) => {
639+
const attrs: Record<string, any> = {
640+
class: 'test2',
641+
};
642+
return <div {...props} class="test component" {...attrs} />;
643+
});
644+
645+
const Parent = component$(() => {
646+
return <Cmp class="test" />;
647+
});
648+
649+
const { vNode } = await render(<Parent />, { debug });
650+
651+
expect(vNode).toMatchVDOM(
652+
<Component>
653+
<Component>
654+
<div class="test2"></div>
655+
</Component>
656+
</Component>
657+
);
658+
});
659+
660+
it('should handle multiple spread element and component props', async () => {
661+
const Cmp = component$((props: PropsOf<'div'>) => {
662+
const attrs: Record<string, any> = {
663+
class: 'test2',
664+
};
665+
return <div {...attrs} class="test component" {...props} />;
666+
});
667+
668+
const Parent = component$(() => {
669+
return <Cmp class="test" />;
670+
});
671+
672+
const { vNode } = await render(<Parent />, { debug });
673+
674+
expect(vNode).toMatchVDOM(
675+
<Component>
676+
<Component>
677+
<div class="test"></div>
678+
</Component>
679+
</Component>
680+
);
681+
});
682+
683+
it('should handle multiple spread element and component props before normal props', async () => {
684+
const Cmp = component$((props: PropsOf<'div'>) => {
685+
const attrs: Record<string, any> = {
686+
class: 'test2',
687+
};
688+
return <div {...attrs} {...props} class="test component" />;
689+
});
690+
691+
const Parent = component$(() => {
692+
return <Cmp class="test" />;
693+
});
694+
695+
const { vNode } = await render(<Parent />, { debug });
696+
697+
expect(vNode).toMatchVDOM(
698+
<Component>
699+
<Component>
700+
<div class="test component"></div>
701+
</Component>
702+
</Component>
703+
);
704+
});
705+
706+
it('should handle multiple spread element and component props after normal props', async () => {
707+
const Cmp = component$((props: PropsOf<'div'>) => {
708+
const attrs: Record<string, any> = {
709+
class: 'test2',
710+
};
711+
return <div class="test component" {...props} {...attrs} />;
712+
});
713+
714+
const Parent = component$(() => {
715+
return <Cmp class="test" />;
716+
});
717+
718+
const { vNode } = await render(<Parent />, { debug });
719+
720+
expect(vNode).toMatchVDOM(
721+
<Component>
722+
<Component>
723+
<div class="test2"></div>
724+
</Component>
725+
</Component>
726+
);
727+
});
728+
});
729+
536730
describe('class attribute', () => {
537731
it('should render class attribute', async () => {
538732
const Cmp = component$(() => {

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__example_jsx.snap

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
---
22
source: packages/qwik/src/optimizer/core/src/test.rs
3-
assertion_line: 1143
3+
assertion_line: 1144
44
expression: output
5-
snapshot_kind: text
65
---
76
==INPUT==
87

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__example_props_optimization.snap

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
---
22
source: packages/qwik/src/optimizer/core/src/test.rs
3-
assertion_line: 515
3+
assertion_line: 516
44
expression: output
5-
snapshot_kind: text
65
---
76
==INPUT==
87

@@ -88,9 +87,9 @@ export const Works = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawPr
8887
_rawProps
8988
], "{some:p0.some??1+2}"),
9089
class: _wrapProp(_rawProps, "count"),
91-
..._getVarProps(rest)
90+
..._getVarProps(rest),
91+
..._getConstProps(rest)
9292
}, {
93-
..._getConstProps(rest),
9493
override: true
9594
}, _wrapProp(_rawProps, "count"), 0, "u6_0");
9695
}, "Works_component_t45qL4vNGv0"));
@@ -122,7 +121,7 @@ export const NoWorks3 = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(({ c
122121
}, "NoWorks3_component_fc13h5yYn14"));
123122

124123

125-
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;;;;;;AAGA,OAAO,MAAM,sBAAQ,sCAAW;;;;;;;;IAO/B,QAAQ,GAAG,WAHX,iBAFA,QAAO;IAMP,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,cARP;QASC,QAAQ,GAAG,WATZ,OASoB,gBANpB,iBAFA,QAAO,aAGP,gBAAqB;;;;;IAOrB,qBACC,UAAC;QAAI,IAAI,qBAXV,QAAO;;;QAWW,MAAM,kBAAE,CAAA;gBAAE,IAAI,KAXhC,QAAO;YAW0B,CAAA;;;QAAG,KAAK;wBAAa;;0BAAA;QAAM,QAAQ;;AAErE,mCAAG;AAEH,OAAO,MAAM,yBAAW,sCAAW,CAAC,EAAC,KAAK,EAAE,OAAO,EAAC,GAAG,EAAC,EAAC;IACxD,QAAQ,GAAG,CAAC;IACZ,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,IAAM;QACZ,QAAQ,GAAG,CAAC;;;;IAEb,qBACC,WAAC;QAAI,OAAO;aAAQ;AAEtB,sCAAG;AAEH,OAAO,MAAM,yBAAW,sCAAW,CAAC,EAAC,KAAK,EAAE,QAAQ,MAAM,EAAC;IAC1D,QAAQ,GAAG,CAAC;IACZ,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,IAAM;QACZ,QAAQ,GAAG,CAAC;;;;IAEb,qBACC,WAAC;QAAI,OAAO;aAAQ;AAEtB,sCAAG\"}")
124+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;;;;;;AAGA,OAAO,MAAM,sBAAQ,sCAAW;;;;;;;;IAO/B,QAAQ,GAAG,WAHX,iBAFA,QAAO;IAMP,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,cARP;QASC,QAAQ,GAAG,WATZ,OASoB,gBANpB,iBAFA,QAAO,aAGP,gBAAqB;;;;;IAOrB,qBACC,UAAC;QAAI,IAAI,qBAXV,QAAO;;;QAWW,MAAM,kBAAE,CAAA;gBAAE,IAAI,KAXhC,QAAO;YAW0B,CAAA;;;QAAG,KAAK;wBAAa;0BAAA;;QAAM,QAAQ;;AAErE,mCAAG;AAEH,OAAO,MAAM,yBAAW,sCAAW,CAAC,EAAC,KAAK,EAAE,OAAO,EAAC,GAAG,EAAC,EAAC;IACxD,QAAQ,GAAG,CAAC;IACZ,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,IAAM;QACZ,QAAQ,GAAG,CAAC;;;;IAEb,qBACC,WAAC;QAAI,OAAO;aAAQ;AAEtB,sCAAG;AAEH,OAAO,MAAM,yBAAW,sCAAW,CAAC,EAAC,KAAK,EAAE,QAAQ,MAAM,EAAC;IAC1D,QAAQ,GAAG,CAAC;IACZ,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,IAAM;QACZ,QAAQ,GAAG,CAAC;;;;IAEb,qBACC,WAAC;QAAI,OAAO;aAAQ;AAEtB,sCAAG\"}")
126125
== DIAGNOSTICS ==
127126

128127
[]

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__example_spread_jsx.snap

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
---
22
source: packages/qwik/src/optimizer/core/src/test.rs
3-
assertion_line: 2366
3+
assertion_line: 2367
44
expression: output
5-
snapshot_kind: text
65
---
76
==INPUT==
87

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__should_destructure_args.snap

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
---
22
source: packages/qwik/src/optimizer/core/src/test.rs
3-
assertion_line: 3621
3+
assertion_line: 3622
44
expression: output
5-
snapshot_kind: text
65
---
76
==INPUT==
87

@@ -62,8 +61,9 @@ export const test_component_LUXeXe0DQrg = (_rawProps)=>{
6261
id: _wrapProp(_rawProps, "id")
6362
}, null, [
6463
/*#__PURE__*/ _jsxSplit("span", {
65-
..._getVarProps(rest)
66-
}, _getConstProps(rest), [
64+
..._getVarProps(rest),
65+
..._getConstProps(rest)
66+
}, null, [
6767
_wrapProp(_rawProps, "message"),
6868
" ",
6969
_wrapProp(_rawProps, "count")
@@ -75,7 +75,7 @@ export const test_component_LUXeXe0DQrg = (_rawProps)=>{
7575
};
7676

7777

78-
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;0CAK4B;;;;;;IACzB,MAAM,UAAU,SAAS;QAAE,SAAS;IAAE,GAAG;QAAE,UAAU;IAAM;IAC3D,QAAQ,OAAO;IACf,MAAM,YAAY,QAAQ,OAAO,GAAG;IACpC,qBACC,WAAC;QAAI,EAAE;;sBACN,UAAC;4BAAS;0BAAA;;YACD;;;sBAET,WAAC;YAAI,OAAM;WAAW;;AAGzB\"}")
78+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;0CAK4B;;;;;;IACzB,MAAM,UAAU,SAAS;QAAE,SAAS;IAAE,GAAG;QAAE,UAAU;IAAM;IAC3D,QAAQ,OAAO;IACf,MAAM,YAAY,QAAQ,OAAO,GAAG;IACpC,qBACC,WAAC;QAAI,EAAE;;sBACN,UAAC;4BAAS;8BAAA;;;YACD;;;sBAET,WAAC;YAAI,OAAM;WAAW;;AAGzB\"}")
7979
/*
8080
{
8181
"origin": "test.tsx",
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
source: packages/qwik/src/optimizer/core/src/test.rs
3+
assertion_line: 4600
4+
expression: output
5+
---
6+
==INPUT==
7+
8+
9+
import { component$ } from '@qwik.dev/core';
10+
11+
export default component$((props) => {
12+
return <div {...props} class={[props.class, 'component']} />;
13+
});
14+
15+
============================= test.js ==
16+
17+
import { componentQrl } from "@qwik.dev/core";
18+
import { qrl } from "@qwik.dev/core";
19+
const i_LUXeXe0DQrg = ()=>import("./test.tsx_test_component_LUXeXe0DQrg");
20+
export default /*#__PURE__*/ componentQrl(/*#__PURE__*/ qrl(i_LUXeXe0DQrg, "test_component_LUXeXe0DQrg"));
21+
22+
23+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;AAGE,6BAAe,6EAEZ\"}")
24+
============================= test.tsx_test_component_LUXeXe0DQrg.js (ENTRY POINT)==
25+
26+
import { _fnSignal } from "@qwik.dev/core";
27+
import { _getConstProps } from "@qwik.dev/core";
28+
import { _getVarProps } from "@qwik.dev/core";
29+
import { _jsxSplit } from "@qwik.dev/core";
30+
export const test_component_LUXeXe0DQrg = (props)=>{
31+
return /*#__PURE__*/ _jsxSplit("div", {
32+
..._getVarProps(props),
33+
..._getConstProps(props),
34+
class: _fnSignal((p0)=>[
35+
p0.class,
36+
'component'
37+
], [
38+
props
39+
], '[p0.class,"component"]')
40+
}, null, null, 0, "u6_0");
41+
};
42+
43+
44+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;0CAG4B,CAAC;IAC1B,qBAAO,UAAC;wBAAQ;0BAAA;QAAO,KAAK,kBAAE;gBAAC,GAAM,KAAK;gBAAE;aAAY;;;;AACzD\"}")
45+
/*
46+
{
47+
"origin": "test.tsx",
48+
"name": "test_component_LUXeXe0DQrg",
49+
"entry": null,
50+
"displayName": "test.tsx_test_component",
51+
"hash": "LUXeXe0DQrg",
52+
"canonicalFilename": "test.tsx_test_component_LUXeXe0DQrg",
53+
"path": "",
54+
"extension": "js",
55+
"parent": null,
56+
"ctxKind": "function",
57+
"ctxName": "component$",
58+
"captures": false,
59+
"loc": [
60+
78,
61+
159
62+
],
63+
"paramNames": [
64+
"props"
65+
]
66+
}
67+
*/
68+
== DIAGNOSTICS ==
69+
70+
[]

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__should_split_spread_props.snap

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
---
22
source: packages/qwik/src/optimizer/core/src/test.rs
3-
assertion_line: 4434
3+
assertion_line: 4435
44
expression: output
5-
snapshot_kind: text
65
---
76
==INPUT==
87

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__should_split_spread_props_with_additional_prop.snap

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
---
22
source: packages/qwik/src/optimizer/core/src/test.rs
3-
assertion_line: 4453
3+
assertion_line: 4454
44
expression: output
5-
snapshot_kind: text
65
---
76
==INPUT==
87

@@ -31,15 +30,15 @@ import { _getVarProps } from "@qwik.dev/core";
3130
import { _jsxSplit } from "@qwik.dev/core";
3231
export const test_component_LUXeXe0DQrg = (props)=>{
3332
return /*#__PURE__*/ _jsxSplit("div", {
34-
..._getVarProps(props)
33+
..._getVarProps(props),
34+
..._getConstProps(props)
3535
}, {
36-
..._getConstProps(props),
3736
test: "test"
3837
}, null, 0, "u6_0");
3938
};
4039

4140

42-
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;0CAG4B,CAAC;IAC1B,qBACC,UAAC;wBAAQ;;0BAAA;QAAO,MAAK;;AAEvB\"}")
41+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;0CAG4B,CAAC;IAC1B,qBACC,UAAC;wBAAQ;0BAAA;;QAAO,MAAK;;AAEvB\"}")
4342
/*
4443
{
4544
"origin": "test.tsx",

0 commit comments

Comments
 (0)