Skip to content

fix: keep the events of inner components inside their composite hosts - #2568

Merged
rkaraivanov merged 5 commits into
masterfrom
rkaraivanov/prevent-event-leakage
Nov 2, 2026
Merged

rkaraivanov merged 5 commits into
masterfrom
rkaraivanov/prevent-event-leakage

Conversation

@rkaraivanov

Copy link
Copy Markdown
Member

Description

  • Calendar: the igcActiveDateChange and igcRangePreviewDateChange events
    of the days view no longer leave the calendar, also in the date
    pickers.
  • Chat: the igcInput and igcChange events of the text area and the
    igcRemove event of the attachment chips stay inside. Use
    igcInputChange and igcAttachmentRemoved.
  • Color picker: the igcInput of the inner inputs, the open and close
    events of the format select and the canvas igcColorPicked stay
    inside.
  • Tests: a guard in the test runner fails a spec file when an inner
    igc* event reaches a component host.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Checklist

  • My code follows the project's coding standards
  • I have tested my changes locally
  • I have updated documentation if needed
  • I have added a CHANGELOG.md entry under [Unreleased]

The igcActiveDateChange and igcRangePreviewDateChange events of the inner
days view no longer reach the listeners on the calendar, the date picker
or the date range picker.
…inside

The igcInput and igcChange events of the inner text area and the igcRemove
event of an attachment chip no longer reach the listeners on the chat.
Use igcInputChange and igcAttachmentRemoved instead.
The igcInput of the alpha input, the color value input and the input
anchor, the open and close events of the format select, and the
igcColorPicked of the canvas no longer reach the listeners on the color
picker. Before, a listener that canceled igcClosing on the picker also
kept the format select open.
- The test runner loads a guard that records each igc* event of an
  element in the shadow root of a component that reaches the outermost
  component host. The file fails in a root after hook, with the test
  titles and the host chain of each leak.
- The combo virtual scroll events are a known exception until the #2530
  fix lands.
- The coding guidelines and the review skill get the rule: a composite
  stops the igc* events of the components in its shadow root.
- A real click on the checkbox of a tree item now has a spec. The item
  cancels the click, so the checkbox sends no igcChange to the tree.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The leak check runs before later root teardown hooks, allowing inner events emitted by those hooks to go unreported; the check must run afterward with regression coverage.

1 open issue
What changed in this PR

This PR keeps internal component events from reaching consumers of composite hosts, preserving the intended public event APIs.

Changes:

  • Stops internal events in calendar, chat, and color picker components.
  • Adds a shared event-leak guard and regression tests, including native keyboard and mouse interactions.
  • Updates component specifications, contributor guidance, and release notes.
File Description
web-test-runner.config.mjs Loads the event-leak guard before the test framework.
src/​internals/​testing/​inner-events.spec.ts Detects leaked internal events and reports test-file failures.
src/​components/​tree/​tree-selection.spec.ts Tests checkbox event containment with a real click.
src/​components/​tree/​spec.md Documents checkbox event containment.
src/​components/​inner-event-guard.spec.ts Tests event-leak detection and exclusions.
src/​components/​color-picker/​spec.md Documents internal event boundaries and test scenarios.
src/​components/​color-picker/​color-picker.ts Stops events from internal inputs, select, and canvas.
src/​components/​color-picker/​color-picker.spec.ts Adds internal event containment tests.
src/​components/​chat/​spec.md Documents containment and public replacement events.
src/​components/​chat/​chat.spec.ts Tests textarea and attachment-chip event containment.
src/​components/​chat/​chat-input.ts Stops internal textarea and chip events.
src/​components/​calendar/​spec.md Documents containment of calendar view events.
src/​components/​calendar/​calendar.ts Stops days-view navigation and range-preview events.
src/​components/​calendar/​calendar.interaction.spec.ts Tests days-view event containment.
CHANGELOG.md Describes event containment fixes and consumer impact.
.github/​CODING_GUIDELINES.md Adds composite event containment guidance.
.agents/​skills/​review-component-pr/​SKILL.md Adds event containment to the review checklist.

Review effort: Balanced

The guard added its checks in mocha.setup(), so they ran before the
root afterEach and after hooks of a spec file, and a leak in such a hook
was never reported. A root before hook now adds the checks when the run
starts, after all root hooks of the spec files.
@rkaraivanov
rkaraivanov merged commit af2ab97 into master Nov 2, 2026
7 checks passed
@rkaraivanov
rkaraivanov deleted the rkaraivanov/prevent-event-leakage branch November 2, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants