Skip to content

fix: prevent panic in event dispatching when element data is missing …#2508

Merged
PupilTong merged 1 commit intolynx-family:mainfrom
PupilTong:p/hw/fix-empty-bubble-path
Apr 22, 2026
Merged

fix: prevent panic in event dispatching when element data is missing …#2508
PupilTong merged 1 commit intolynx-family:mainfrom
PupilTong:p/hw/fix-empty-bubble-path

Conversation

@PupilTong
Copy link
Copy Markdown
Collaborator

@PupilTong PupilTong commented Apr 22, 2026

…and add regression tests

Summary by CodeRabbit

  • Bug Fixes
    • Fixed event dispatching crash when handling events on missing or invalid elements
    • Improved robustness of event propagation in edge cases

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).
  • Changeset added, and when a BREAKING CHANGE occurs, it needs to be clearly marked (or not required).

@PupilTong PupilTong requested a review from Sherry-hue as a code owner April 22, 2026 10:26
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 22, 2026

🦋 Changeset detected

Latest commit: c5f070c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@lynx-js/web-core Patch
upgrade-rspeedy Patch
@lynx-js/web-rsbuild-server-middleware Patch
@lynx-js/template-webpack-plugin Patch
@lynx-js/react-rsbuild-plugin Patch
create-rspeedy Patch
@lynx-js/web-worker-rpc Patch
@lynx-js/react-alias-rsbuild-plugin Patch
@lynx-js/rspeedy Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@PupilTong PupilTong self-assigned this Apr 22, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

📝 Walkthrough

Walkthrough

This PR fixes a panic in the dispatch_event_by_path function by replacing unsafe unwrap() calls with proper error handling. When element bindings are missing during event dispatch, the function now gracefully returns false or skips the iteration rather than panicking.

Changes

Cohort / File(s) Summary
Changesets Documentation
.changeset/fix-event-apis-panic.md
Records a patch version bump for @lynx-js/web-core documenting the panic prevention fix.
Event API Safety Hardening
packages/web-platform/web-core/src/main_thread/client/element_apis/event_apis.rs
Replaces two unwrap() calls in dispatch_event_by_path with match expressions to safely handle missing element bindings; returns false when target binding is absent, and skips iterations when intermediate bindings are missing.
Event Handling Test Coverage
packages/web-platform/web-core/tests/element-apis.spec.ts
Adds two new test cases verifying common_event_handler does not panic when invoked with a non-existent uniqueId in the bubblePath or with an empty bubblePath.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested labels

platform:Web

Suggested reviewers

  • Sherry-hue

Poem

🐰 A panic did lurk in the events so grand,
With unwrap() calls scattered across the land,
But a rabbit hopped in with a match in hand,
Now missing bindings are handled so planned! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: preventing a panic in event dispatching when element data is missing, which matches the core purpose of all modifications across the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 22, 2026

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
.../src/main_thread/client/element_apis/event_apis.rs 0.00% 6 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/web-platform/web-core/src/main_thread/client/element_apis/event_apis.rs (1)

167-179: ⚠️ Potential issue | 🔴 Critical

Handle missing element data gracefully in get_event and get_events like other event APIs do.

Lines 167 and 178 still use .unwrap() which will panic if element data is missing. The recent fix (commit c5f070c) addressed this panic risk in dispatch_event_by_path (returning false) and common_event_handler (using match with graceful handling). However, get_event and get_events were excluded from that fix.

Since these methods are called from JS via __GetEvent and __GetEvents with uniqueIds extracted from DOM elements, stale IDs from removed elements can cause panics. Other similar public methods in component_apis.rs and dataset_apis.rs return Result<T, JsError> instead. Consider updating get_event and get_events to follow the same pattern—either returning Result<T, JsError> or using graceful error handling consistent with dispatch_event_by_path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/web-platform/web-core/src/main_thread/client/element_apis/event_apis.rs`
around lines 167 - 179, get_event and get_events currently call
self.get_element_data_by_unique_id(...).unwrap() which can panic for
stale/missing elements; change them to handle missing element data gracefully
like dispatch_event_by_path and common_event_handler: replace the unwrap() usage
in get_event and get_events with a match or early-return that converts the
missing element case into a JS-friendly error (e.g., return Result<JsValue,
JsError> for get_event and Result<Vec<EventInfo>, JsError> for get_events) or
return a sensible default/error value, ensuring you use the same error
creation/JsError helper used elsewhere so JS callers (__GetEvent/__GetEvents)
receive a non-panicking failure instead of a panic.
🧹 Nitpick comments (1)
packages/web-platform/web-core/tests/element-apis.spec.ts (1)

82-117: Dead event locals in both new tests.

event is constructed via document.createEvent(...) / initEvent(...) but never used — the tests pass eventObject to common_event_handler. Dropping the unused setup keeps the regression tests focused.

♻️ Proposed cleanup
   test('#commonEventHandler should not crash on invalid uniqueId', () => {
-    // We send an event with a bubblePath containing a non-existent uniqueId
     const invalidUniqueId = 999999;
-    const event = document.createEvent('Event') as any;
-    event.initEvent('touchstart', true, true);
-
-    // Create cross thread event manually for the test
     const eventObject = { type: 'touchstart', detail: {} } as any;
...
   test('#commonEventHandler should not crash on empty path', () => {
-    // We send an event with a bubblePath containing a non-existent uniqueId
-    const event = document.createEvent('Event') as any;
-    event.initEvent('touchstart', true, true);
-
-    // Create cross thread event manually for the test
     const eventObject = { type: 'touchstart', detail: {} } as any;

Also consider strengthening the assertion beyond not.toThrow() — e.g. spy on mtsBinding.publishEvent and assert it is not called for the invalid/empty cases, so a future regression that silently dispatches to the wrong element would still fail.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/web-platform/web-core/tests/element-apis.spec.ts` around lines 82 -
117, Remove the dead local `event` setup in both tests "#commonEventHandler
should not crash on invalid uniqueId" and "#commonEventHandler should not crash
on empty path" (the `document.createEvent(...)` and `initEvent(...)` lines)
since the tests call mtsBinding.wasmContext!.common_event_handler with
`eventObject`; then optionally strengthen the assertions by spying on
`mtsBinding.publishEvent` (or equivalent) and asserting it was not called for
the invalidUniqueId and empty Uint32Array cases to ensure no silent dispatch
happens.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@packages/web-platform/web-core/src/main_thread/client/element_apis/event_apis.rs`:
- Around line 212-218: The code currently uses
bubble_unique_id_path.first().cloned().unwrap_or_default() which maps an empty
path to target_unique_id = 0 and then looks up get_element_data_by_unique_id(0);
change this to explicitly handle an empty bubble_unique_id_path by returning
false (or early exit) before computing target_unique_id so you don't
accidentally resolve to a real element with id 0; update the logic around
bubble_unique_id_path, target_unique_id, and the match on
get_element_data_by_unique_id to check bubble_unique_id_path.is_empty() first
and bail out before calling get_element_data_by_unique_id.

---

Outside diff comments:
In
`@packages/web-platform/web-core/src/main_thread/client/element_apis/event_apis.rs`:
- Around line 167-179: get_event and get_events currently call
self.get_element_data_by_unique_id(...).unwrap() which can panic for
stale/missing elements; change them to handle missing element data gracefully
like dispatch_event_by_path and common_event_handler: replace the unwrap() usage
in get_event and get_events with a match or early-return that converts the
missing element case into a JS-friendly error (e.g., return Result<JsValue,
JsError> for get_event and Result<Vec<EventInfo>, JsError> for get_events) or
return a sensible default/error value, ensuring you use the same error
creation/JsError helper used elsewhere so JS callers (__GetEvent/__GetEvents)
receive a non-panicking failure instead of a panic.

---

Nitpick comments:
In `@packages/web-platform/web-core/tests/element-apis.spec.ts`:
- Around line 82-117: Remove the dead local `event` setup in both tests
"#commonEventHandler should not crash on invalid uniqueId" and
"#commonEventHandler should not crash on empty path" (the
`document.createEvent(...)` and `initEvent(...)` lines) since the tests call
mtsBinding.wasmContext!.common_event_handler with `eventObject`; then optionally
strengthen the assertions by spying on `mtsBinding.publishEvent` (or equivalent)
and asserting it was not called for the invalidUniqueId and empty Uint32Array
cases to ensure no silent dispatch happens.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5301e0a0-d179-4fbb-a4fe-79d382e779c1

📥 Commits

Reviewing files that changed from the base of the PR and between eec539a and c5f070c.

📒 Files selected for processing (3)
  • .changeset/fix-event-apis-panic.md
  • packages/web-platform/web-core/src/main_thread/client/element_apis/event_apis.rs
  • packages/web-platform/web-core/tests/element-apis.spec.ts

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 22, 2026

Merging this PR will improve performance by 23.84%

⚡ 2 improved benchmarks
✅ 79 untouched benchmarks
⏩ 26 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
003-hello-list-destroyBackground 3.4 ms 2.8 ms +23.84%
transform 1000 view elements 46.8 ms 39.9 ms +17.18%

Comparing PupilTong:p/hw/fix-empty-bubble-path (c5f070c) with main (ea5e30e)2

Open in CodSpeed

Footnotes

  1. 26 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (eec539a) during the generation of this report, so ea5e30e was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Apr 22, 2026

React External

#633 Bundle Size — 674.83KiB (0%).

c5f070c(current) vs ea5e30e main#622(baseline)

Bundle metrics  no changes
                 Current
#633
     Baseline
#622
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 0% 98.35%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 17 17
No change  Duplicate Modules 5 5
No change  Duplicate Code 8.59% 8.59%
No change  Packages 0 0
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#633
     Baseline
#622
No change  Other 674.83KiB 674.83KiB

Bundle analysis reportBranch PupilTong:p/hw/fix-empty-bubble-...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Apr 22, 2026

React Example

#7515 Bundle Size — 224.41KiB (0%).

c5f070c(current) vs ea5e30e main#7504(baseline)

Bundle metrics  no changes
                 Current
#7515
     Baseline
#7504
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 4 4
No change  Modules 179 179
No change  Duplicate Modules 69 69
No change  Duplicate Code 44.51% 44.51%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#7515
     Baseline
#7504
No change  IMG 145.76KiB 145.76KiB
No change  Other 78.65KiB 78.65KiB

Bundle analysis reportBranch PupilTong:p/hw/fix-empty-bubble-...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Apr 22, 2026

React MTF Example

#647 Bundle Size — 195.57KiB (0%).

c5f070c(current) vs ea5e30e main#637(baseline)

Bundle metrics  no changes
                 Current
#647
     Baseline
#637
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 173 173
No change  Duplicate Modules 66 66
No change  Duplicate Code 44% 44%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#647
     Baseline
#637
No change  IMG 111.23KiB 111.23KiB
No change  Other 84.34KiB 84.34KiB

Bundle analysis reportBranch PupilTong:p/hw/fix-empty-bubble-...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Apr 22, 2026

Web Explorer

#9087 Bundle Size — 899.79KiB (+0.12%).

c5f070c(current) vs ea5e30e main#9077(baseline)

Bundle metrics  Change 2 changes
                 Current
#9087
     Baseline
#9077
No change  Initial JS 44.46KiB 44.46KiB
No change  Initial CSS 2.22KiB 2.22KiB
Change  Cache Invalidation 43.7% 0%
No change  Chunks 9 9
No change  Assets 11 11
No change  Modules 229 229
No change  Duplicate Modules 11 11
Change  Duplicate Code 27.2%(-0.07%) 27.22%
No change  Packages 10 10
No change  Duplicate Packages 0 0
Bundle size by type  Change 2 changes Regression 1 regression Improvement 1 improvement
                 Current
#9087
     Baseline
#9077
Regression  JS 495.65KiB (+0.24%) 494.47KiB
Improvement  Other 401.92KiB (-0.02%) 402.02KiB
No change  CSS 2.22KiB 2.22KiB

Bundle analysis reportBranch PupilTong:p/hw/fix-empty-bubble-...Project dashboard


Generated by RelativeCIDocumentationReport issue

@PupilTong PupilTong merged commit 1d4abfc into lynx-family:main Apr 22, 2026
49 of 51 checks passed
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