Skip to content

Commit 243e40d

Browse files
committed
Devin: try to fix inline if helper bug
1 parent 809e52a commit 243e40d

File tree

2 files changed

+216
-1
lines changed

2 files changed

+216
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import {
2+
GlimmerishComponent,
3+
jitSuite,
4+
RenderTest,
5+
strip,
6+
test,
7+
tracked,
8+
} from '@glimmer-workspace/integration-tests';
9+
10+
class IfInlineTest extends RenderTest {
11+
static suiteName = 'Helpers test: inline {{if}}';
12+
13+
@test
14+
'inline if helper updates when tracked property changes'() {
15+
class Person {
16+
@tracked isActive = false;
17+
18+
toggle() {
19+
this.isActive = !this.isActive;
20+
}
21+
}
22+
23+
const person = new Person();
24+
25+
this.render(
26+
strip`<div>{{if this.person.isActive "Active" "Inactive"}}</div>`,
27+
{ person }
28+
);
29+
30+
this.assertHTML('<div>Inactive</div>', 'Initial render shows inactive state');
31+
this.assertStableRerender();
32+
33+
person.toggle();
34+
this.rerender();
35+
this.assertHTML('<div>Active</div>', 'Updates when tracked property changes to true');
36+
37+
person.toggle();
38+
this.rerender();
39+
this.assertHTML('<div>Inactive</div>', 'Updates when tracked property changes to false');
40+
}
41+
42+
@test
43+
'inline if helper with only truthy value updates when tracked property changes'() {
44+
class Person {
45+
@tracked isActive = false;
46+
47+
toggle() {
48+
this.isActive = !this.isActive;
49+
}
50+
}
51+
52+
const person = new Person();
53+
54+
this.render(
55+
strip`<div>{{if this.person.isActive "Active"}}</div>`,
56+
{ person }
57+
);
58+
59+
this.assertHTML('<div></div>', 'Initial render shows empty when false');
60+
this.assertStableRerender();
61+
62+
person.toggle();
63+
this.rerender();
64+
this.assertHTML('<div>Active</div>', 'Updates when tracked property changes to true');
65+
66+
person.toggle();
67+
this.rerender();
68+
this.assertHTML('<div></div>', 'Updates when tracked property changes to false');
69+
}
70+
71+
@test
72+
'inline if helper updates when component argument changes'() {
73+
let testComponent: TestComponent;
74+
75+
class TestComponent extends GlimmerishComponent {
76+
@tracked isActive = false;
77+
78+
constructor(owner: object, args: Record<string, unknown>) {
79+
super(owner, args);
80+
testComponent = this;
81+
}
82+
}
83+
84+
this.registerComponent(
85+
'Glimmer',
86+
'TestComponent',
87+
'{{if @isActive "Active" "Inactive"}}',
88+
TestComponent
89+
);
90+
91+
this.render(
92+
strip`<TestComponent @isActive={{this.isActive}} />`,
93+
{ isActive: false }
94+
);
95+
96+
this.assertHTML('Inactive', 'Initial render shows inactive state');
97+
this.assertStableRerender();
98+
99+
this.rerender({ isActive: true });
100+
this.assertHTML('Active', 'Updates when argument changes to true');
101+
102+
this.rerender({ isActive: false });
103+
this.assertHTML('Inactive', 'Updates when argument changes to false');
104+
}
105+
106+
@test
107+
'inline if helper with components updates when tracked property changes'() {
108+
class Person {
109+
@tracked isActive = false;
110+
111+
toggle() {
112+
this.isActive = !this.isActive;
113+
}
114+
}
115+
116+
const person = new Person();
117+
118+
class OkComponent extends GlimmerishComponent {}
119+
class KoComponent extends GlimmerishComponent {}
120+
121+
this.registerComponent('Glimmer', 'Ok', '<div>OK Component</div>', OkComponent);
122+
this.registerComponent('Glimmer', 'Ko', '<div>KO Component</div>', KoComponent);
123+
124+
this.render(
125+
strip`<div>{{if this.person.isActive Ok Ko}}</div>`,
126+
{ person }
127+
);
128+
129+
this.assertHTML('<div><div>KO Component</div></div>', 'Initial render shows KO component');
130+
this.assertStableRerender();
131+
132+
person.toggle();
133+
this.rerender();
134+
this.assertHTML('<div><div>OK Component</div></div>', 'Updates to OK component when tracked property changes to true');
135+
136+
person.toggle();
137+
this.rerender();
138+
this.assertHTML('<div><div>KO Component</div></div>', 'Updates to KO component when tracked property changes to false');
139+
}
140+
141+
@test
142+
'inline if helper with components updates when component argument changes'() {
143+
class OkComponent extends GlimmerishComponent {}
144+
class KoComponent extends GlimmerishComponent {}
145+
146+
this.registerComponent('Glimmer', 'Ok', '<div>OK Component</div>', OkComponent);
147+
this.registerComponent('Glimmer', 'Ko', '<div>KO Component</div>', KoComponent);
148+
149+
this.registerComponent(
150+
'Glimmer',
151+
'TestComponent',
152+
'{{if @isOk Ok Ko}}',
153+
class extends GlimmerishComponent {}
154+
);
155+
156+
this.render(
157+
strip`<TestComponent @isOk={{this.isOk}} />`,
158+
{ isOk: false }
159+
);
160+
161+
this.assertHTML('<div>KO Component</div>', 'Initial render shows KO component');
162+
this.assertStableRerender();
163+
164+
this.rerender({ isOk: true });
165+
this.assertHTML('<div>OK Component</div>', 'Updates to OK component when argument changes to true');
166+
167+
this.rerender({ isOk: false });
168+
this.assertHTML('<div>KO Component</div>', 'Updates to KO component when argument changes to false');
169+
}
170+
171+
@test
172+
'comparison with block form if helper using components'() {
173+
class Person {
174+
@tracked isActive = false;
175+
176+
toggle() {
177+
this.isActive = !this.isActive;
178+
}
179+
}
180+
181+
const person = new Person();
182+
183+
class OkComponent extends GlimmerishComponent {}
184+
class KoComponent extends GlimmerishComponent {}
185+
186+
this.registerComponent('Glimmer', 'Ok', '<div>OK Component</div>', OkComponent);
187+
this.registerComponent('Glimmer', 'Ko', '<div>KO Component</div>', KoComponent);
188+
189+
this.render(
190+
strip`
191+
<div>
192+
Inline: {{if this.person.isActive Ok Ko}}
193+
Block: {{#if this.person.isActive}}<Ok />{{else}}<Ko />{{/if}}
194+
</div>
195+
`,
196+
{ person }
197+
);
198+
199+
this.assertHTML('<div>Inline: <div>KO Component</div> Block: <div>KO Component</div></div>', 'Initial render both show KO component');
200+
this.assertStableRerender();
201+
202+
person.toggle();
203+
this.rerender();
204+
this.assertHTML('<div>Inline: <div>OK Component</div> Block: <div>OK Component</div></div>', 'Both update to OK component when tracked property changes to true');
205+
206+
person.toggle();
207+
this.rerender();
208+
this.assertHTML('<div>Inline: <div>KO Component</div> Block: <div>KO Component</div></div>', 'Both update to KO component when tracked property changes to false');
209+
}
210+
}
211+
212+
jitSuite(IfInlineTest);

packages/@glimmer/runtime/lib/compiled/opcodes/expressions.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,10 @@ APPEND_OPCODES.add(VM_IF_INLINE_OP, (vm) => {
285285

286286
vm.stack.push(
287287
createComputeRef(() => {
288-
if (toBool(valueForRef(condition))) {
288+
// Explicitly consume the condition reference to ensure tracking
289+
let conditionValue = valueForRef(condition);
290+
291+
if (toBool(conditionValue)) {
289292
return valueForRef(truthy);
290293
} else {
291294
return valueForRef(falsy);

0 commit comments

Comments
 (0)