Skip to content
Closed
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
12 changes: 11 additions & 1 deletion src/diff/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,17 @@ export function setProperty(dom, name, value, oldValue, namespace) {
}
}
// Benchmark for comparison: https://esbench.com/bench/574c954bdb965b9a00965ac6
else if (name[0] == 'o' && name[1] == 'n') {
// Custom elements may have non-event properties/attributes starting with
// `on` (https://github.com/preactjs/preact/issues/4085), so for tag names
// containing a `-` only treat `on*` props as event handlers when the new
// or old value is a function.
else if (
name[0] == 'o' &&
name[1] == 'n' &&
(typeof value == 'function' ||

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

short-circuit so there shouldn't be an extra cost for normal execution)

typeof oldValue == 'function' ||
dom.localName.indexOf('-') == -1)
) {
useCapture = name != (name = name.replace(CAPTURE_REGEX, '$1'));

// Infer correct casing for DOM built-in events:
Expand Down
26 changes: 26 additions & 0 deletions test/browser/events.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,32 @@ describe('event handling', () => {
);
});

// see https://github.com/preactjs/preact/issues/4085
it('should set non-function on* props on custom elements as attributes', () => {
render(<my-tooltip only-when-overflow={true} for="a1" />, scratch);

let el = scratch.firstChild;
expect(el.getAttribute('only-when-overflow')).to.equal('true');
expect(el._listeners).to.equal(undefined);

render(<my-tooltip for="a1" />, scratch);
expect(el.hasAttribute('only-when-overflow')).to.equal(false);
});

it('should register function on* props on custom elements as handlers', () => {
let click = vi.fn();

render(<my-tooltip onClick={click} />, scratch);

fireEvent(scratch.firstChild, 'click');
expect(click).toHaveBeenCalledOnce();

render(<my-tooltip onClick={null} />, scratch);

fireEvent(scratch.firstChild, 'click');
expect(click).toHaveBeenCalledOnce();
});

it('should support camel-case focus event names', () => {
render(<div onFocusIn={() => {}} onFocusOut={() => {}} />, scratch);

Expand Down
Loading