Skip to content

Commit 79e7055

Browse files
committedFeb 16, 2024
Fix issue with dynamic modifiers infinitely receiving duplicate arguments
1 parent 4727694 commit 79e7055

File tree

3 files changed

+29
-39
lines changed

3 files changed

+29
-39
lines changed
 

‎packages/@glimmer-workspace/integration-tests/test/modifiers/dynamic-modifiers-test.ts

+22
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,28 @@ class DynamicModifiersResolutionModeTest extends RenderTest {
6565
this.assertStableRerender();
6666
}
6767

68+
@test
69+
'Modifiers with dynamic arguments receive the correct number of arguments'(assert) {
70+
let receivedArgs: unknown[] = [];
71+
const foo = defineSimpleModifier(
72+
(_element: unknown, args: unknown[]) => (receivedArgs = args)
73+
);
74+
75+
this.render(`
76+
{{~#let (modifier this.foo this.outer) as |foo|~}}
77+
<div {{ (if this.cond (modifier foo this.inner)) }}>General Kenobi!</div>
78+
{{~/let~}}
79+
`, { foo, inner: 'x', outer: 'y', cond: true });
80+
81+
this.assertHTML('<div>General Kenobi!</div>');
82+
this.assertStableRerender();
83+
assert.deepEqual(receivedArgs, ['y', 'x']);
84+
this.rerender({ cond: false });
85+
this.rerender({ cond: true });
86+
assert.deepEqual(receivedArgs, ['y', 'x']);
87+
88+
}
89+
6890
@test
6991
'Can pass curried modifier as argument and invoke dynamically (with args)'() {
7092
const foo = defineSimpleModifier(

‎packages/@glimmer-workspace/integration-tests/test/modifiers/on-test.ts

-32
Original file line numberDiff line numberDiff line change
@@ -315,38 +315,6 @@ if (hasDom) {
315315
this.assertCounts({ adds: 1, removes: 0 });
316316
}
317317

318-
@test
319-
'updates to a (remaining truthy) condition do not leave the element without an attached modifier'(assert:
320-
Assert) {
321-
let calledCount = 0;
322-
323-
this.render(`
324-
<button {{
325-
(if this.condition
326-
(modifier this.on "click" this.callback)
327-
)
328-
}}>Click Me</button>`, {
329-
callback() {
330-
calledCount++;
331-
},
332-
on,
333-
condition: true,
334-
});
335-
336-
this.findButton().click();
337-
assert.strictEqual(calledCount, 1, 'callback is being invoked');
338-
339-
this.rerender({ condition: true });
340-
341-
this.findButton().click();
342-
assert.strictEqual(calledCount, 2, 'callback is being invoked');
343-
344-
this.rerender({ condition: true });
345-
346-
this.findButton().click();
347-
assert.strictEqual(calledCount, 3, 'callback is being invoked');
348-
}
349-
350318
@test
351319
'asserts when eventName is missing'(assert: Assert) {
352320
assert.throws(() => {

‎packages/@glimmer/runtime/lib/compiled/opcodes/dom.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
import { associateDestroyableChild, destroy } from '@glimmer/destroyable';
2323
import { getInternalModifierManager } from '@glimmer/manager';
2424
import { createComputeRef, isConstRef, valueForRef } from '@glimmer/reference';
25-
import { assign, debugToString, expect, isObject } from '@glimmer/util';
25+
import { debugToString, expect, isObject } from '@glimmer/util';
2626
import { consumeTag, CURRENT_TAG, validateTag, valueForTag } from '@glimmer/validator';
2727
import { $t0, CurriedTypes, Op } from '@glimmer/vm';
2828

@@ -153,6 +153,8 @@ APPEND_OPCODES.add(Op.DynamicModifier, (vm) => {
153153
let { stack } = vm;
154154
let ref = check(stack.pop(), CheckReference);
155155
let args = check(stack.pop(), CheckArguments).capture();
156+
let { positional: outerPositional, named: outerNamed } = args;
157+
156158
let { constructing } = vm.elements();
157159
let initialOwner = vm.getOwner();
158160

@@ -178,11 +180,11 @@ APPEND_OPCODES.add(Op.DynamicModifier, (vm) => {
178180
owner = curriedOwner;
179181

180182
if (positional !== undefined) {
181-
args.positional = positional.concat(args.positional) as CapturedPositionalArguments;
183+
args.positional = [...positional, ...outerPositional] as CapturedPositionalArguments;
182184
}
183185

184186
if (named !== undefined) {
185-
args.named = assign({}, ...named, args.named);
187+
args.named = Object.assign({}, named, outerNamed);
186188
}
187189
} else {
188190
hostDefinition = value;
@@ -194,10 +196,8 @@ APPEND_OPCODES.add(Op.DynamicModifier, (vm) => {
194196
if (manager === null) {
195197
if (import.meta.env.DEV) {
196198
throw new Error(
197-
`Expected a dynamic modifier definition, but received an object or function that did not have a modifier manager associated with it. The dynamic invocation was \`{{${
198-
ref.debugLabel
199-
}}}\`, and the incorrect definition is the value at the path \`${
200-
ref.debugLabel
199+
`Expected a dynamic modifier definition, but received an object or function that did not have a modifier manager associated with it. The dynamic invocation was \`{{${ref.debugLabel
200+
}}}\`, and the incorrect definition is the value at the path \`${ref.debugLabel
201201
}\`, which was: ${debugToString!(hostDefinition)}`
202202
);
203203
} else {

0 commit comments

Comments
 (0)