Skip to content

Commit 795c51f

Browse files
committed
fix(optimizer): only rewrite map-to-Each inside JSX children
1 parent ef8a2aa commit 795c51f

7 files changed

Lines changed: 319 additions & 55 deletions

packages/optimizer/core/src/snapshots/qwik_core__test__example_component_with_event_listeners_inside_loop.snap

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
source: packages/optimizer/core/src/test.rs
3+
assertion_line: 3979
34
expression: output
45
---
56
==INPUT==
@@ -486,26 +487,6 @@ Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"ma
486487
== DIAGNOSTICS ==
487488

488489
[
489-
{
490-
"category": "warning",
491-
"code": "map-to-each",
492-
"file": "test.tsx",
493-
"message": "This .map() was not optimized to Each because the returned JSX node is missing a key.",
494-
"highlights": [
495-
{
496-
"lo": 257,
497-
"hi": 432,
498-
"startLine": 7,
499-
"startCol": 16,
500-
"endLine": 15,
501-
"endCol": 10
502-
}
503-
],
504-
"suggestions": [
505-
"Add a stable key to the returned JSX node."
506-
],
507-
"scope": "optimizer"
508-
},
509490
{
510491
"category": "warning",
511492
"code": "map-to-each",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
source: packages/optimizer/core/src/test.rs
3+
assertion_line: 7231
4+
expression: output
5+
---
6+
==INPUT==
7+
8+
9+
import { component$ } from '@qwik.dev/core';
10+
11+
export const App = component$(() => {
12+
const items = [{ id: 'a', text: 'A' }];
13+
const renderItems = () => items.map((item) => <span key={item.id}>{item.text}</span>);
14+
return <div>{renderItems()}</div>;
15+
});
16+
17+
============================= test.js ==
18+
19+
import { componentQrl } from "@qwik.dev/core";
20+
import { qrl } from "@qwik.dev/core";
21+
//
22+
const q_App_component_ckEPmXZlub0 = /*#__PURE__*/ qrl(()=>import("./test.tsx_App_component_ckEPmXZlub0"), "App_component_ckEPmXZlub0");
23+
//
24+
export const App = /*#__PURE__*/ componentQrl(q_App_component_ckEPmXZlub0);
25+
26+
27+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;AAGA,OAAO,MAAM,oBAAM,0CAIhB\"}")
28+
============================= test.tsx_App_component_ckEPmXZlub0.js (ENTRY POINT)==
29+
30+
import { _jsxSorted } from "@qwik.dev/core";
31+
import { _wrapProp } from "@qwik.dev/core";
32+
//
33+
export const App_component_ckEPmXZlub0 = ()=>{
34+
const items = [
35+
{
36+
id: 'a',
37+
text: 'A'
38+
}
39+
];
40+
const renderItems = ()=>items.map((item)=>/*#__PURE__*/ _jsxSorted("span", null, null, _wrapProp(item, "text"), 1, item.id));
41+
return /*#__PURE__*/ _jsxSorted("div", null, null, renderItems(), 1, "u6_0");
42+
};
43+
44+
45+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;yCAG8B;IAC5B,MAAM,QAAQ;QAAC;YAAE,IAAI;YAAK,MAAM;QAAI;KAAE;IACtC,MAAM,cAAc,IAAM,MAAM,GAAG,CAAC,CAAC,qBAAS,WAAC,8BAAoB,kBAAV,KAAK,EAAE;IAChE,qBAAO,WAAC,mBAAK;AACf\"}")
46+
/*
47+
{
48+
"origin": "test.tsx",
49+
"name": "App_component_ckEPmXZlub0",
50+
"entry": null,
51+
"displayName": "test.tsx_App_component",
52+
"hash": "ckEPmXZlub0",
53+
"canonicalFilename": "test.tsx_App_component_ckEPmXZlub0",
54+
"path": "",
55+
"extension": "js",
56+
"parent": null,
57+
"ctxKind": "function",
58+
"ctxName": "component$",
59+
"captures": false,
60+
"loc": [
61+
78,
62+
255
63+
]
64+
}
65+
*/
66+
== DIAGNOSTICS ==
67+
68+
[]
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
source: packages/optimizer/core/src/test.rs
3+
assertion_line: 7211
4+
expression: output
5+
---
6+
==INPUT==
7+
8+
9+
import { component$ } from '@qwik.dev/core';
10+
11+
export const App = component$(() => {
12+
const items = [{ id: 'a', text: 'A' }];
13+
const rendered = items.map((item) => <span key={item.id}>{item.text}</span>);
14+
return <div>{rendered}</div>;
15+
});
16+
17+
============================= test.js ==
18+
19+
import { componentQrl } from "@qwik.dev/core";
20+
import { qrl } from "@qwik.dev/core";
21+
//
22+
const q_App_component_ckEPmXZlub0 = /*#__PURE__*/ qrl(()=>import("./test.tsx_App_component_ckEPmXZlub0"), "App_component_ckEPmXZlub0");
23+
//
24+
export const App = /*#__PURE__*/ componentQrl(q_App_component_ckEPmXZlub0);
25+
26+
27+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;AAGA,OAAO,MAAM,oBAAM,0CAIhB\"}")
28+
============================= test.tsx_App_component_ckEPmXZlub0.js (ENTRY POINT)==
29+
30+
import { _jsxSorted } from "@qwik.dev/core";
31+
import { _wrapProp } from "@qwik.dev/core";
32+
//
33+
export const App_component_ckEPmXZlub0 = ()=>{
34+
const items = [
35+
{
36+
id: 'a',
37+
text: 'A'
38+
}
39+
];
40+
const rendered = items.map((item)=>/*#__PURE__*/ _jsxSorted("span", null, null, _wrapProp(item, "text"), 1, item.id));
41+
return /*#__PURE__*/ _jsxSorted("div", null, null, rendered, 1, "u6_0");
42+
};
43+
44+
45+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;yCAG8B;IAC5B,MAAM,QAAQ;QAAC;YAAE,IAAI;YAAK,MAAM;QAAI;KAAE;IACtC,MAAM,WAAW,MAAM,GAAG,CAAC,CAAC,qBAAS,WAAC,8BAAoB,kBAAV,KAAK,EAAE;IACvD,qBAAO,WAAC,mBAAK;AACf\"}")
46+
/*
47+
{
48+
"origin": "test.tsx",
49+
"name": "App_component_ckEPmXZlub0",
50+
"entry": null,
51+
"displayName": "test.tsx_App_component",
52+
"hash": "ckEPmXZlub0",
53+
"canonicalFilename": "test.tsx_App_component_ckEPmXZlub0",
54+
"path": "",
55+
"extension": "js",
56+
"parent": null,
57+
"ctxKind": "function",
58+
"ctxName": "component$",
59+
"captures": false,
60+
"loc": [
61+
78,
62+
241
63+
]
64+
}
65+
*/
66+
== DIAGNOSTICS ==
67+
68+
[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
source: packages/optimizer/core/src/test.rs
3+
assertion_line: 7251
4+
expression: output
5+
---
6+
==INPUT==
7+
8+
9+
import { component$ } from '@qwik.dev/core';
10+
11+
export const App = component$(() => {
12+
const items = [{ id: 'a', text: 'A' }];
13+
const rendered = items.map((item) => <span key={item.id}>{item.text}</span>);
14+
return <div>{rendered}</div>;
15+
});
16+
17+
============================= test.tsx ==
18+
19+
import { componentQrl } from "@qwik.dev/core";
20+
import { qrl } from "@qwik.dev/core";
21+
//
22+
const q_App_component_ckEPmXZlub0 = /*#__PURE__*/ qrl(()=>import("./test.tsx_App_component_ckEPmXZlub0"), "App_component_ckEPmXZlub0");
23+
//
24+
export const App = /*#__PURE__*/ componentQrl(q_App_component_ckEPmXZlub0);
25+
26+
27+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;AAGA,OAAO,MAAM,oBAAM,0CAIhB\"}")
28+
============================= test.tsx_App_component_ckEPmXZlub0.tsx (ENTRY POINT)==
29+
30+
export const App_component_ckEPmXZlub0 = ()=>{
31+
const items = [
32+
{
33+
id: 'a',
34+
text: 'A'
35+
}
36+
];
37+
const rendered = items.map((item)=><span key={item.id}>{item.text}</span>);
38+
return <div>{rendered}</div>;
39+
};
40+
41+
42+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\"yCAG8B;IAC5B,MAAM,QAAQ;QAAC;YAAE,IAAI;YAAK,MAAM;QAAI;KAAE;IACtC,MAAM,WAAW,MAAM,GAAG,CAAC,CAAC,QAAU,KAAK,KAAK,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG;IACtE,QAAQ,KAAK,WAAW;AAC1B\"}")
43+
/*
44+
{
45+
"origin": "test.tsx",
46+
"name": "App_component_ckEPmXZlub0",
47+
"entry": null,
48+
"displayName": "test.tsx_App_component",
49+
"hash": "ckEPmXZlub0",
50+
"canonicalFilename": "test.tsx_App_component_ckEPmXZlub0",
51+
"path": "",
52+
"extension": "tsx",
53+
"parent": null,
54+
"ctxKind": "function",
55+
"ctxName": "component$",
56+
"captures": false,
57+
"loc": [
58+
78,
59+
241
60+
]
61+
}
62+
*/
63+
== DIAGNOSTICS ==
64+
65+
[]

packages/optimizer/core/src/test.rs

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7043,14 +7043,12 @@ export const App = component$(() => {
70437043
let combined_code = combined_modules_code(&output);
70447044

70457045
assert!(
7046-
combined_code.contains("_jsxSorted(Each")
7047-
|| combined_code.contains("_jsxSplit(Each"),
7046+
combined_code.contains("_jsxSorted(Each") || combined_code.contains("_jsxSplit(Each"),
70487047
"Expected Each render in generated output.\n{}",
70497048
combined_code
70507049
);
70517050
assert!(
7052-
!combined_code.contains(".map((item)=>")
7053-
&& !combined_code.contains(".map(item=>"),
7051+
!combined_code.contains(".map((item)=>") && !combined_code.contains(".map(item=>"),
70547052
"Expected map callback to be rewritten.\n{}",
70557053
combined_code
70567054
);
@@ -7208,6 +7206,66 @@ export const App = component$(() => {
72087206
);
72097207
}
72107208

7209+
#[test]
7210+
fn snapshot_map_to_each_outside_jsx_children_is_not_rewritten() {
7211+
test_input!(TestInput {
7212+
code: r#"
7213+
import { component$ } from '@qwik.dev/core';
7214+
7215+
export const App = component$(() => {
7216+
const items = [{ id: 'a', text: 'A' }];
7217+
const rendered = items.map((item) => <span key={item.id}>{item.text}</span>);
7218+
return <div>{rendered}</div>;
7219+
});
7220+
"#
7221+
.to_string(),
7222+
transpile_ts: true,
7223+
transpile_jsx: true,
7224+
snapshot: true,
7225+
..TestInput::default()
7226+
});
7227+
}
7228+
7229+
#[test]
7230+
fn snapshot_map_to_each_inside_normal_function_is_not_rewritten() {
7231+
test_input!(TestInput {
7232+
code: r#"
7233+
import { component$ } from '@qwik.dev/core';
7234+
7235+
export const App = component$(() => {
7236+
const items = [{ id: 'a', text: 'A' }];
7237+
const renderItems = () => items.map((item) => <span key={item.id}>{item.text}</span>);
7238+
return <div>{renderItems()}</div>;
7239+
});
7240+
"#
7241+
.to_string(),
7242+
transpile_ts: true,
7243+
transpile_jsx: true,
7244+
snapshot: true,
7245+
..TestInput::default()
7246+
});
7247+
}
7248+
7249+
#[test]
7250+
fn snapshot_map_to_each_outside_jsx_children_without_jsx_transpile_is_not_rewritten() {
7251+
test_input!(TestInput {
7252+
code: r#"
7253+
import { component$ } from '@qwik.dev/core';
7254+
7255+
export const App = component$(() => {
7256+
const items = [{ id: 'a', text: 'A' }];
7257+
const rendered = items.map((item) => <span key={item.id}>{item.text}</span>);
7258+
return <div>{rendered}</div>;
7259+
});
7260+
"#
7261+
.to_string(),
7262+
transpile_ts: false,
7263+
transpile_jsx: false,
7264+
snapshot: true,
7265+
..TestInput::default()
7266+
});
7267+
}
7268+
72117269
#[test]
72127270
fn should_not_transform_map_to_each_when_disabled_by_comment() {
72137271
let res = test_input!(TestInput {

0 commit comments

Comments
 (0)