Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,91 @@ class DynamicStrictModeTest extends RenderTest {
this.assertStableRerender();
}

@test
'Can use a dynamic component with a changing definition (append position)'(assert: Assert) {
const Foo = defineComponent({}, 'Hello, world!', {
definition: class extends GlimmerishComponent {
override willDestroy() {
assert.step('willDestroy 1 called');
}
},
});

const Bar = defineComponent({}, 'Hello, earth!', {
definition: class extends GlimmerishComponent {
override willDestroy() {
assert.step('willDestroy 2 called');
}
},
});

const Baz = defineComponent({}, '{{@Foo}}');

let args = trackedObj({ Foo });

this.renderComponent(Baz, args);
this.assertHTML('Hello, world!');
this.assertStableRerender();

args['Foo'] = Bar;

this.rerender();
this.assertHTML('Hello, earth!');
this.assertStableRerender();
assert.verifySteps(['willDestroy 1 called']);

args['Foo'] = undefined;

this.rerender();
this.assertHTML('');
this.assertStableRerender();
assert.verifySteps(['willDestroy 2 called']);
}

@test
'Can use a dynamic component with a changing definition (append position, with args)'() {
const Foo = defineComponent({}, 'Hello, {{@value}}!');
const Bar = defineComponent({}, 'Goodbye, {{@value}}!');
const Baz = defineComponent({}, '{{@Foo value="world"}}');

let args = trackedObj({ Foo });

this.renderComponent(Baz, args);
this.assertHTML('Hello, world!');
this.assertStableRerender();

args['Foo'] = Bar;

this.rerender();
this.assertHTML('Goodbye, world!');
this.assertStableRerender();
}

@test
'Can use an inline if to swap components in append position'() {
const Ok = defineComponent({}, 'Ok');
const Ko = defineComponent({}, 'Ko');
const Foo = defineComponent({ Ok, Ko }, '{{if @isOk Ok Ko}}');

let args = trackedObj({ isOk: true });

this.renderComponent(Foo, args);
this.assertHTML('Ok');
this.assertStableRerender();

args['isOk'] = false;

this.rerender();
this.assertHTML('Ko');
this.assertStableRerender();

args['isOk'] = true;

this.rerender();
this.assertHTML('Ok');
this.assertStableRerender();
}

@test
'Can use a dynamic component in block position'() {
const Foo = defineComponent({}, 'Hello, {{yield}}');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions packages/@glimmer/opcode-compiler/lib/syntax/statements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
WireFormat,
} from '@glimmer/interfaces';
import {
VM_ASSERT_SAME_OP,
VM_CLOSE_ELEMENT_OP,
VM_COMMENT_OP,
VM_COMPONENT_ATTR_OP,
Expand Down Expand Up @@ -218,6 +219,7 @@ STATEMENTS.add(SexpOpcodes.Append, (op, [, value]) => {
},
(when) => {
when(ContentType.Component, () => {
op(VM_ASSERT_SAME_OP);
op(VM_RESOLVE_CURRIED_COMPONENT_OP);
op(VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP);
InvokeNonStaticComponent(op, {
Expand Down
Loading