Skip to content

fix: reduce redundant updates for handlers and gestures#2188

Draft
Yradex wants to merge 2 commits intolynx-family:mainfrom
Yradex:wt/mts-support-use-callback-20260202
Draft

fix: reduce redundant updates for handlers and gestures#2188
Yradex wants to merge 2 commits intolynx-family:mainfrom
Yradex:wt/mts-support-use-callback-20260202

Conversation

@Yradex
Copy link
Collaborator

@Yradex Yradex commented Feb 3, 2026

  • Implement copy-on-commit for worklets, gestures, and spread props to avoid background-side mutation.
  • Prevent _execId churn for stable references, reducing redundant native patches.
  • Fix gesture removal cleanup when removed from spread props.
  • Add regression tests for execId churn and gesture cleanup.
  • Add changeset for @lynx-js/react-runtime.

Summary by CodeRabbit

  • Bug Fixes

    • Reduced redundant updates when event handlers, gestures, or spread props stay stable across rerenders; removed gestures now reliably clear native gesture state and stale attributes.
  • Tests

    • Added unit and snapshot tests validating gesture serialization, immutability, removal behavior, and reduced update churn.
  • Documentation

    • Added patch notes describing the fixes and observed behavior.

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).

@Yradex Yradex requested review from HuJean and hzy as code owners February 3, 2026 07:37
@changeset-bot
Copy link

changeset-bot bot commented Feb 3, 2026

🦋 Changeset detected

Latest commit: 23f46ef

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

This PR includes changesets to release 1 package
Name Type
@lynx-js/react 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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 3, 2026

📝 Walkthrough

Walkthrough

Adds copy-on-commit preparation for worklets, spreads, and gestures; replaces in-place mutations with prepare-* helpers; ensures removed gestures clear native DOM state; introduces unit and snapshot tests and a changelog entry documenting reduced execId/snapshot churn for stable references.

Changes

Cohort / File(s) Summary
Changeset
\.changeset/fix-react-runtime-execid-churn.md
Adds release note describing a fix that reduces redundant updates when main-thread handlers, spread props, or gestures remain semantically stable.
Unit tests — gesture commit & removal
packages/react/runtime/__test__/gesture/prepareGestureForCommit.test.js, packages/react/runtime/__test__/gesture/processGesture-remove.test.js
Adds tests validating prepare-for-commit cloning/serialization behavior and that removing or non-serialized gestures clears native DOM gesture attributes.
Snapshot tests — execId churn
packages/react/runtime/__test__/snapshot/mtf-execid-churn.test.jsx
Adds integration tests asserting no snapshotPatch is produced when main-thread handlers, spread props, or gesture objects remain semantically stable across renders/hydration.
Gesture processing implementation
packages/react/runtime/src/gesture/processGesture.ts, packages/react/runtime/src/gesture/processGestureBagkround.ts
Introduces prepareGestureForCommit, copy-on-commit semantics, safe committed toJSON, and clears DOM attributes when gestures are removed; replaces processGestureBackground with prepareGestureForCommit export.
Background snapshot / commit prep
packages/react/runtime/src/backgroundSnapshot.ts
Adds prepareWorkletForCommit and prepareSpreadForCommit; replaces in-place spread/worklet/gesture mutations with prepare-* helpers in setAttributeImpl, hydration, and related flows.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • HuJean
  • hzy

Poem

🐇 I clone what I must and tuck the rest away,
No needless hops when commits come to play.
Stable hands stay still, old gestures swept clean,
Snapshots whisper quiet where chaos had been—
A soft thump, a tidy runtime day.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: reduce redundant updates for handlers and gestures' directly aligns with the main objective of the PR, which implements copy-on-commit semantics and prevents _execId churn for stable references to reduce redundant native patches.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 482ffeaefc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Yradex Yradex force-pushed the wt/mts-support-use-callback-20260202 branch from 482ffea to 77dec4b Compare February 3, 2026 07:42
Copy link
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

🤖 Fix all issues with AI agents
In `@packages/react/runtime/src/gesture/processGestureBagkround.ts`:
- Around line 45-51: The committedCallbacks cloning assumes every callback is
non-null and calls prepareWorkletForCommit(...)! which will throw when a
callback is null/undefined; update the loop over committedCallbacks (the object
derived from baseGesture.callbacks) to check each committedCallbacks[name] for
null/undefined and only call prepareWorkletForCommit when it is present,
otherwise leave the entry as-is (remove the non-null assertions and skip calling
prepareWorkletForCommit for null/undefined values) so null callbacks are
preserved and not spread into worklets.

@codecov
Copy link

codecov bot commented Feb 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

- Implement copy-on-commit for worklets, gestures, and spread props to avoid background-side mutation.
- Prevent _execId churn for stable references, reducing redundant native patches.
- Fix gesture removal cleanup when removed from spread props.
- Add regression tests for execId churn and gesture cleanup.
- Add changeset for @lynx-js/react-runtime.
@Yradex Yradex force-pushed the wt/mts-support-use-callback-20260202 branch from 77dec4b to b09eaa9 Compare February 3, 2026 07:53
Copy link
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

🤖 Fix all issues with AI agents
In `@packages/react/runtime/__test__/snapshot/mtf-execid-churn.test.jsx`:
- Around line 142-199: The test reads lynx.getNativeApp().callLepusMethod too
soon after the background render, causing a race; after render(<Comp tick={1}
/>, __root) in the "rerender with no semantic changes" block, await the
scheduled patch (e.g., await Promise.resolve() or flush pending
timers/microtasks) before switching back to main thread and accessing
lynx.getNativeApp().callLepusMethod.mock.calls so that
getSnapshotPatchFromPatchUpdateCall sees the finalized call.
🧹 Nitpick comments (1)
packages/react/runtime/__test__/snapshot/mtf-execid-churn.test.jsx (1)

12-16: Make helper failures explicit instead of a TypeError.
If call or call[1].data is missing, the current code throws a vague error. Adding explicit assertions makes failures easier to diagnose.

Suggested change
 function getSnapshotPatchFromPatchUpdateCall(call) {
-  const obj = call[1];
-  const parsed = JSON.parse(obj.data);
+  expect(call, 'expected a patch update call').toBeTruthy();
+  const obj = call[1];
+  expect(obj?.data, 'expected patch payload').toBeTypeOf('string');
+  const parsed = JSON.parse(obj.data);
   return parsed.patchList?.[0]?.snapshotPatch;
 }

@relativeci
Copy link

relativeci bot commented Feb 3, 2026

Web Explorer

#7528 Bundle Size — 383.66KiB (0%).

23f46ef(current) vs e2d349e main#7526(baseline)

Bundle metrics  no changes
                 Current
#7528
     Baseline
#7526
No change  Initial JS 154.82KiB 154.82KiB
No change  Initial CSS 35.05KiB 35.05KiB
Change  Cache Invalidation 0% 40.35%
No change  Chunks 8 8
No change  Assets 8 8
No change  Modules 238 238
No change  Duplicate Modules 16 16
No change  Duplicate Code 2.99% 2.99%
No change  Packages 4 4
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#7528
     Baseline
#7526
No change  JS 252.76KiB 252.76KiB
No change  Other 95.85KiB 95.85KiB
No change  CSS 35.05KiB 35.05KiB

Bundle analysis reportBranch Yradex:wt/mts-support-use-callba...Project dashboard


Generated by RelativeCIDocumentationReport issue

Copy link
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: 2

🤖 Fix all issues with AI agents
In `@packages/react/runtime/__test__/snapshot/mtf-execid-churn.test.jsx`:
- Around line 26-34: The test overrides a global value but never restores it;
capture the original SystemInfo.lynxSdkVersion in the beforeEach (e.g., const
originalLynxSdkVersion = SystemInfo.lynxSdkVersion) before setting
SystemInfo.lynxSdkVersion = '999.999', and then restore it in afterEach (set
SystemInfo.lynxSdkVersion = originalLynxSdkVersion) alongside
vi.restoreAllMocks() and elementTree.clear() to prevent cross-test leakage.
- Around line 20-24: Tests mutate global state via injectUpdateMainThread
(assigning globalThis['rLynxChange']) and patch Preact's options.commit via
replaceCommitHook/hook(), so add an afterAll() that deletes
globalThis['rLynxChange'] and restores options.commit to its original value (use
the original reference captured by hook() or reset options.commit to
undefined/default) in the mtf-execid-churn.test.jsx file so test globals are
cleaned up in addition to vi.restoreAllMocks().

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 3, 2026

CodSpeed Performance Report

Merging this PR will degrade performance by 22.78%

Comparing Yradex:wt/mts-support-use-callback-20260202 (23f46ef) with main (e2d349e)

Summary

❌ 3 regressed benchmarks
✅ 60 untouched benchmarks
⏩ 3 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
004-various-update-setAttribute__BatchedValues 316.1 µs 409.3 µs -22.78%
004-various-update__main-thread-setAttribute__MT_Event 95.9 µs 111.2 µs -13.76%
basic-performance-nest-level-100 7.1 ms 7.8 ms -9.15%

Footnotes

  1. 3 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.

@Yradex Yradex marked this pull request as draft February 4, 2026 04:11
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