Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -390,4 +390,4 @@
}
},
"packageManager": "pnpm@10.5.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { moduleFor, RenderingTestCase, runTask } from 'internal-test-helpers';
import { getInternalModifierManager } from '@glimmer/manager';
import { on } from '@glimmer/runtime';

import { DEBUG } from '@glimmer/env';

import { Component } from '../../utils/helpers';

moduleFor(
Expand Down Expand Up @@ -31,7 +33,7 @@ moduleFor(
);
}

['@test it adds an event listener'](assert) {
[`@test it adds an event listener`](assert) {
let count = 0;

this.render('<button {{on "click" this.callback}}>Click Me</button>', {
Expand Down Expand Up @@ -242,6 +244,30 @@ moduleFor(

this.assertCounts({ adds: 1, removes: 1 });
}

[`@test it throws a helpful error when callback is undefined`](assert) {
if (DEBUG) {
let expectedMessage =
/You must pass a function as the second argument to the `on` modifier/;
assert.throws(() => {
this.render('<button {{on "click" undefined}}>Click Me</button>');
}, expectedMessage);
} else {
assert.expect(0);
}
}

[`@test it throws a helpful error when callback is null`](assert) {
if (DEBUG) {
let expectedMessage =
/You must pass a function as the second argument to the `on` modifier/;
assert.throws(() => {
this.render('<button {{on "click" null}}>Click Me</button>');
}, expectedMessage);
} else {
assert.expect(0);
}
}
}
);

Expand Down
26 changes: 17 additions & 9 deletions packages/@glimmer/runtime/lib/modifiers/on.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,24 @@ export class OnModifierState {
() => 'You must pass a valid DOM event name as the first argument to the `on` modifier'
);

localAssert(
args.positional[1],
'You must pass a function as the second argument to the `on` modifier'
);
let arg1 = args.positional[1];
let userProvidedCallback = check(
arg1 ? valueForRef(arg1) : undefined,
CheckFunction,
(actual) => {
return `You must pass a function as the second argument to the \`on\` modifier; you passed ${
actual === null ? 'null' : typeof actual
}. While rendering:\n\n${args.positional[1]?.debugLabel ?? `{unlabeled value}`}`;
}
) as EventListener;

let userProvidedCallback = check(valueForRef(args.positional[1]), CheckFunction, (actual) => {
return `You must pass a function as the second argument to the \`on\` modifier; you passed ${
actual === null ? 'null' : typeof actual
}. While rendering:\n\n${args.positional[1]?.debugLabel ?? `{unlabeled value}`}`;
}) as EventListener;
if (DEBUG && typeof userProvidedCallback !== 'function') {
throw new Error(
`You must pass a function as the second argument to the \`on\` modifier; you passed ${
userProvidedCallback === null ? 'null' : typeof userProvidedCallback
}. While rendering:\n\n${args.positional[1]?.debugLabel ?? `{unlabeled value}`}`
);
}

if (DEBUG && args.positional.length !== 2) {
throw new Error(
Expand Down