Skip to content

test(ownts): runtime confirmation that the two OSS true positives really leak#207

Merged
PhysShell merged 2 commits into
mainfrom
claude/ts-useeffect-github-action-docs-2pegns
Jul 10, 2026
Merged

test(ownts): runtime confirmation that the two OSS true positives really leak#207
PhysShell merged 2 commits into
mainfrom
claude/ts-useeffect-github-action-docs-2pegns

Conversation

@PhysShell

@PhysShell PhysShell commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Что и зачем

Добавляет frontend/ownts/oss-verify — независимое исполняемое подтверждение, что две true-positive находки из docs/notes/ownts-oss-benchmark.md (react-scroll-to-bottom@4.2.0 capture-mismatch и @reactuses/core@6.4.0 fresh-fn-identity) — реальные утечки слушателей в DOM, а не то, с чем анализатор просто соглашается сам с собой. Формы прогоняются в настоящем DOM (jsdom): регистрируем слушатель → выполняем cleanup эффекта → диспатчим событие; срабатывание хендлера после cleanup = утечка.

Тип изменения

  • feat — новая возможность
  • fix — исправление бага
  • docs — документация
  • refactor / chore / test / ci — без изменения поведения

Как проверено

  • python tests/run_tests.py
  • ruff check . и mypy
  • новый прогон: cd frontend/ownts/oss-verify && npm ci && npm test# tests 5 # pass 5 # fail 0 (2 leak-доказательства + 2 корректных-cleanup контроля + 1 проверка root-cause идентичности функции). Каждый leak-кейс парный с контролем, который обязан остаться «тихим», — так ассерты неложные. Кросс-проверено в живом Chromium (результат совпадает, зафиксирован в README). Новый CI-джоб — ownts-oss-verify.

Связанные issue

Refs docs/notes/ownts-oss-benchmark.md («First confirmed TRUE positive»). Отдельного issue нет.

Чеклист

  • изменение покрыто тестом/селфтестом (или объяснено, почему нет) — само изменение и есть тест
  • README/docs обновлены при необходимости — frontend/ownts/oss-verify/README.md (провенанс: pkg@version:line + upstream sha256; таблица jsdom↔Chromium; политика «чужой код не вендорим»)
  • коммиты в conventional-commit стиле (feat:, fix:, docs: …)

🤖 Generated with Claude Code


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added runtime verification for two documented DOM event-listener leak cases, including matching cleanup controls.
    • Verification runs across simulated browser environments and headless Chromium.
  • Documentation

    • Added reproducibility guidance, test instructions, case details, and provenance information.
  • Tests

    • Added automated checks confirming leaked listeners remain active while correctly cleaned-up listeners do not fire.
    • Integrated verification into continuous integration.

Adds frontend/ownts/oss-verify — an independent, executable check that the two
true positives in docs/notes/ownts-oss-benchmark.md are real DOM listener leaks,
not just findings the analyzer agrees with itself on.

- react-scroll-to-bottom@4.2.0 Composer.js:574 — addEventListener({capture:true})
  torn down by removeEventListener with the default (false) capture; the flag is
  part of the removal key, so the listener is never removed.
- @reactuses/core@6.4.0 index.mjs — onPressed = t => () => {…}, so onPressed('mouse')
  is a fresh function at add and again at remove; identities differ, so the
  drag/touch listeners are never removed.

Each shape is run in a real DOM (jsdom): register -> run the effect's cleanup ->
dispatch; the handler still firing proves the leak. Paired correct-cleanup controls
must go silent, so the leak assertions are non-vacuous. Cross-checked in real
Chromium (identical result, recorded in the README).

Reduced cases are authored here with pkg@version:line + upstream sha256 provenance;
no third-party source is vendored (repo policy). Wired into CI as ownts-oss-verify.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JsBjTfMzCm15fZ616nM1cz
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@PhysShell, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f7590726-0af6-4588-a754-43574777dc6f

📥 Commits

Reviewing files that changed from the base of the PR and between 1c59e84 and 52cb593.

📒 Files selected for processing (2)
  • frontend/ownts/oss-verify/README.md
  • frontend/ownts/oss-verify/oss-true-positives.test.mjs
📝 Walkthrough

Walkthrough

Adds a jsdom runtime verification package for two OwnTS OSS listener leaks, matching cleanup controls, documentation, dependency setup, and a GitHub Actions job that runs the tests.

Changes

OwnTS OSS runtime verification

Layer / File(s) Summary
Verification package and DOM harness
frontend/ownts/oss-verify/package.json, frontend/ownts/oss-verify/oss-true-positives.test.mjs, .gitignore
Defines the private Node ESM test package, pins jsdom, creates isolated DOM instances, and ignores local dependencies.
Leak and cleanup control cases
frontend/ownts/oss-verify/oss-true-positives.test.mjs
Validates listener leaks caused by capture-option mismatch and fresh handler identity, with corresponding correct-cleanup controls.
CI execution and verification documentation
.github/workflows/ci.yml, frontend/ownts/oss-verify/README.md
Documents the verification cases and configures CI to install dependencies and run the test suite.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • PhysShell/Own.NET#145: Covers matching listener receiver, handler identity, and capture options when determining whether an event listener is released.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding runtime verification that two OSS true positives really leak.
Description check ✅ Passed The description follows the required template and fills all sections with specific, relevant details.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/ts-useeffect-github-action-docs-2pegns

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.

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

Copy link
Copy Markdown

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: 1c59e84500

ℹ️ 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".

Comment on lines +93 to +95
element.addEventListener("dragstart", onPressed("mouse"));
// effect cleanup, as published — a *different* freshly-returned fn
element.removeEventListener("dragstart", onPressed("mouse"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Verify the actual ReactUse listener shape

When this job is used as the runtime proof for @reactuses/core@6.4.0, these lines test a fresh-function identity mismatch (onPressed("mouse") at add/remove), but the cited package's published dist/index.mjs uses useEventListener/useDraggable with stable listener functions and leaks because cleanup drops the capture/options argument. Because the reduced case is not the package shape named in the README, CI can pass while failing to confirm (or catch regressions in) the actual OSS true positive.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Thanks — checked this against the published tarball (npm pack @reactuses/core@6.4.0, dist/index.mjs). The cited hook is useMousePressed, and the listeners are not stable functions:

const onPressed = useCallback((srcType) => () => { setPressed(true); setSourceType(srcType); }, []);
...
element.addEventListener('dragstart', onPressed('mouse'), listenerOptions$2); // :2830
...
element.removeEventListener('dragstart', onPressed('mouse'));                  // :2846

onPressed('mouse') is a curried call that returns a fresh function at add and again at remove, so the identities differ — that's the leak, matching the reduced case (and the benchmark note). The dropped argument is listenerOptions$2 = { passive: true } (:2809), which is not the cause: a listener's removal key is (type, callback, capture)passive isn't part of it, and no capture is set (false on both sides).

That said, your fidelity point was fair: the reduced case had omitted the option. Fixed in 52cb593 — the case-2 leak test now adds with { passive: true } and removes without it (the package's exact shape), and a new control adds with the option and removes without it yet still goes clean, isolating the option-drop as a red herring. Still 5/5.


Generated by Claude Code

…te option-drop

Codex review flagged that the reduced case for @reactuses/core@6.4.0 might not be
the published shape. The published hook (useMousePressed) adds the drag/touch
listeners with listenerOptions$2 = { passive: true } and removes them without it.
The leak, however, is the fresh onPressed('mouse') identity (a curried
useCallback), not the dropped option: `passive` is not part of a listener's
removal key and no capture is set.

- add now passes { passive: true } (as published); remove omits it — exact shape.
- the case-2 control adds WITH the option and removes WITHOUT it and still goes
  clean, proving the option-drop is a red herring and identity is the sole cause.
- README/provenance updated (hook name, listenerOptions$2 line, the note).

Still 5/5 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JsBjTfMzCm15fZ616nM1cz
@PhysShell
PhysShell merged commit 4edf672 into main Jul 10, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants