From f4e66fe56f7bdeb8dfe6e2c5ebb5a1886aa96089 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 6 May 2026 23:15:11 +0000 Subject: [PATCH 1/3] Initial plan From 0743417797da59fe91030bf82316b1b575ad674f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 7 May 2026 00:06:28 +0000 Subject: [PATCH 2/3] Add tests for inline if/unless with arg as condition [GH #21042] Agent-Logs-Url: https://github.com/emberjs/ember.js/sessions/eeaec1fb-7e92-497a-9eae-adcc5fbc23b9 Co-authored-by: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> --- .../integration-tests/test/updating-test.ts | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/packages/@glimmer-workspace/integration-tests/test/updating-test.ts b/packages/@glimmer-workspace/integration-tests/test/updating-test.ts index 46f2c627834..2f4eda48a1e 100644 --- a/packages/@glimmer-workspace/integration-tests/test/updating-test.ts +++ b/packages/@glimmer-workspace/integration-tests/test/updating-test.ts @@ -792,6 +792,98 @@ class UpdatingTest extends RenderTest { this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); } + @test + 'if keyword in append position with arg as condition [GH emberjs/ember.js#21042]'() { + this.registerComponent('TemplateOnly', 'Foo', '{{if @condition "truthy"}}'); + this.render('', { + condition: true, + }); + + this.assertHTML('truthy', 'Initial render'); + + this.rerender({ condition: false }); + this.assertHTML('', 'If the condition is false nothing renders'); + + this.rerender({ condition: true }); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + } + + @test + 'if keyword in append position with arg as condition with falsy [GH emberjs/ember.js#21042]'() { + this.registerComponent('TemplateOnly', 'Foo', '{{if @condition "truthy" "falsy"}}'); + this.render('', { + condition: true, + }); + + this.assertHTML('truthy', 'Initial render'); + + this.rerender({ condition: false }); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + + this.rerender({ condition: true }); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + } + + @test + 'unless keyword in append position with arg as condition [GH emberjs/ember.js#21042]'() { + this.registerComponent('TemplateOnly', 'Foo', '{{unless @condition "falsy"}}'); + this.render('', { + condition: false, + }); + + this.assertHTML('falsy', 'Initial render'); + + this.rerender({ condition: true }); + this.assertHTML('', 'If the condition is true nothing renders'); + + this.rerender({ condition: false }); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + } + + @test + 'unless keyword in append position with arg as condition with truthy [GH emberjs/ember.js#21042]'() { + this.registerComponent('TemplateOnly', 'Foo', '{{unless @condition "falsy" "truthy"}}'); + this.render('', { + condition: false, + }); + + this.assertHTML('falsy', 'Initial render'); + + this.rerender({ condition: true }); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + + this.rerender({ condition: false }); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + } + + @test + 'if keyword in append position with @tracked arg as condition [GH emberjs/ember.js#21042]'() { + let parentInstance!: ParentComponent; + + class ParentComponent extends GlimmerishComponent { + @tracked condition = true; + + constructor(owner: object, args: Record) { + super(owner, args); + parentInstance = this; + } + } + + this.registerComponent('TemplateOnly', 'Foo', '{{if @condition "truthy" "falsy"}}'); + this.registerComponent('Glimmer', 'Parent', '', ParentComponent); + this.render(''); + + this.assertHTML('truthy', 'Initial render'); + + parentInstance.condition = false; + this.rerender(); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + + parentInstance.condition = true; + this.rerender(); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + } + @test 'unless keyword in call position'() { this.registerComponent('TemplateOnly', 'Foo', '{{@value}}'); From 13ad9c6ed61a4f1a459f1095e32cf2a8b0f0b2ee Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 7 May 2026 07:14:36 +0000 Subject: [PATCH 3/3] Fix inline if/unless with component args: add VM_ASSERT_SAME_OP for component branch Agent-Logs-Url: https://github.com/emberjs/ember.js/sessions/c9384514-8a79-4fd1-997c-859207137897 Co-authored-by: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> --- .../integration-tests/test/updating-test.ts | 109 ++++++++---------- .../lib/opcode-builder/helpers/stdlib.ts | 1 + 2 files changed, 46 insertions(+), 64 deletions(-) diff --git a/packages/@glimmer-workspace/integration-tests/test/updating-test.ts b/packages/@glimmer-workspace/integration-tests/test/updating-test.ts index 2f4eda48a1e..3f6eeff4b83 100644 --- a/packages/@glimmer-workspace/integration-tests/test/updating-test.ts +++ b/packages/@glimmer-workspace/integration-tests/test/updating-test.ts @@ -7,6 +7,7 @@ import { createComputeRef, createConstRef, createPrimitiveRef } from '@glimmer/r import { consumeTag, createTag, dirtyTag } from '@glimmer/validator'; import { assertNodeTagName, + defineComponent, getElementByClassName, getElementsByTagName, GlimmerishComponent, @@ -15,6 +16,7 @@ import { stripTight, test, tracked, + trackedObj, trimLines, } from '@glimmer-workspace/integration-tests'; @@ -794,94 +796,73 @@ class UpdatingTest extends RenderTest { @test 'if keyword in append position with arg as condition [GH emberjs/ember.js#21042]'() { - this.registerComponent('TemplateOnly', 'Foo', '{{if @condition "truthy"}}'); - this.render('', { - condition: true, - }); + const Ok = defineComponent({}, 'ok'); + const Ko = defineComponent({}, 'ko'); + const Flipper = defineComponent({ Ok, Ko }, '{{if @isOk Ok Ko}}'); - this.assertHTML('truthy', 'Initial render'); + let args = trackedObj({ isOk: true }); - this.rerender({ condition: false }); - this.assertHTML('', 'If the condition is false nothing renders'); - - this.rerender({ condition: true }); - this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); - } - - @test - 'if keyword in append position with arg as condition with falsy [GH emberjs/ember.js#21042]'() { - this.registerComponent('TemplateOnly', 'Foo', '{{if @condition "truthy" "falsy"}}'); - this.render('', { - condition: true, - }); + this.renderComponent(Flipper, args); + this.assertHTML('ok', 'Initial render'); - this.assertHTML('truthy', 'Initial render'); - - this.rerender({ condition: false }); - this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + args['isOk'] = false; + this.rerender(); + this.assertHTML('ko', 'If the condition is false, the falsy component renders'); - this.rerender({ condition: true }); - this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + args['isOk'] = true; + this.rerender(); + this.assertHTML('ok', 'If the condition is true, the truthy component renders'); } @test 'unless keyword in append position with arg as condition [GH emberjs/ember.js#21042]'() { - this.registerComponent('TemplateOnly', 'Foo', '{{unless @condition "falsy"}}'); - this.render('', { - condition: false, - }); - - this.assertHTML('falsy', 'Initial render'); + const Ok = defineComponent({}, 'ok'); + const Ko = defineComponent({}, 'ko'); + const Flipper = defineComponent({ Ok, Ko }, '{{unless @isOk Ko Ok}}'); - this.rerender({ condition: true }); - this.assertHTML('', 'If the condition is true nothing renders'); + let args = trackedObj({ isOk: false }); - this.rerender({ condition: false }); - this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); - } + this.renderComponent(Flipper, args); + this.assertHTML('ko', 'Initial render'); - @test - 'unless keyword in append position with arg as condition with truthy [GH emberjs/ember.js#21042]'() { - this.registerComponent('TemplateOnly', 'Foo', '{{unless @condition "falsy" "truthy"}}'); - this.render('', { - condition: false, - }); - - this.assertHTML('falsy', 'Initial render'); - - this.rerender({ condition: true }); - this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + args['isOk'] = true; + this.rerender(); + this.assertHTML('ok', 'If the condition is true, the truthy component renders'); - this.rerender({ condition: false }); - this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + args['isOk'] = false; + this.rerender(); + this.assertHTML('ko', 'If the condition is false, the falsy component renders'); } @test 'if keyword in append position with @tracked arg as condition [GH emberjs/ember.js#21042]'() { - let parentInstance!: ParentComponent; + const Ok = defineComponent({}, 'ok'); + const Ko = defineComponent({}, 'ko'); + const Flipper = defineComponent({ Ok, Ko }, '{{if @isOk Ok Ko}}'); - class ParentComponent extends GlimmerishComponent { - @tracked condition = true; + let instance!: { isOk: boolean }; - constructor(owner: object, args: Record) { - super(owner, args); - parentInstance = this; - } - } + const Demo = defineComponent({ Flipper }, '', { + definition: class extends GlimmerishComponent { + @tracked isOk = true; - this.registerComponent('TemplateOnly', 'Foo', '{{if @condition "truthy" "falsy"}}'); - this.registerComponent('Glimmer', 'Parent', '', ParentComponent); - this.render(''); + constructor(owner: object, args: Record) { + super(owner, args); + instance = this; + } + }, + }); - this.assertHTML('truthy', 'Initial render'); + this.renderComponent(Demo); + this.assertHTML('ok', 'Initial render'); - parentInstance.condition = false; + instance.isOk = false; this.rerender(); - this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + this.assertHTML('ko', 'If the condition is false, the falsy component renders'); - parentInstance.condition = true; + instance.isOk = true; this.rerender(); - this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + this.assertHTML('ok', 'If the condition is true, the truthy component renders'); } @test diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/stdlib.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/stdlib.ts index 466add49cc9..4f4b29746ea 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/stdlib.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/stdlib.ts @@ -56,6 +56,7 @@ export function StdAppend( if (typeof nonDynamicAppend === 'number') { when(ContentType.Component, () => { + op(VM_ASSERT_SAME_OP); op(VM_RESOLVE_CURRIED_COMPONENT_OP); op(VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP); InvokeBareComponent(op);