Skip to content

Conversation

@juno-the-programmer
Copy link

@juno-the-programmer juno-the-programmer commented Jan 2, 2026

  • Add nonce prop to Portal component for Content Security Policy compliance
  • Update useScrollLocker to accept nonce option for dynamic style injection
  • Refactor useScrollLocker to support both boolean and options object parameter
  • Add comprehensive test coverage for nonce functionality
  • Maintain backward compatibility with existing boolean parameter usage

This enables Portal to work in strict CSP environments by allowing developers to pass a nonce attribute for dynamically injected styles used in scroll locking.

Summary by CodeRabbit

发版说明

  • 新功能

    • Portal 组件现已支持 nonce 属性,增强安全集成能力。
    • useScrollLocker 钩子扩展支持配置对象参数。
  • 测试

    • 新增 nonce 功能的完整测试套件,覆盖自动锁定、自定义容器和边界情况等场景。

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 2, 2026

概览

该PR为Portal和useScrollLocker组件添加了CSP nonce支持。新增可选的nonce属性,通过Portal传递给useScrollLocker,后者在动态生成的样式标签上应用该值。同时添加了全面的测试覆盖。

变更

文件分组 / 文件 变更摘要
Portal组件更新
src/Portal.tsx
添加可选nonce?: string属性到PortalProps;引入shouldLock计算值;更新scroll locking调用以传递nonce参数用于CSP保护
Scroll Locker增强
src/useScrollLocker.tsx
新增UseScrollLockerOptions接口,支持locknonce属性;扩展函数签名接受boolean或UseScrollLockerOptions对象;在动态CSS更新时应用nonce;依赖数组中添加nonce
测试覆盖扩展
tests/index.test.tsx
添加"nonce"测试套件,覆盖:autoLock启用/禁用时的nonce应用、Portal关闭时的清理、自定义容器兼容性、未定义nonce处理、StrictMode兼容性等场景

评估代码审查工作量

🎯 2 (Simple) | ⏱️ ~12 分钟

🐰✨ 兔兔来庆贺新变更
CSP nonce护航样式飞,
安全策略此处生花,
Portal与Locker齐协力,
测试周全无遗漏,
码农安心好睡眠。

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰准确地总结了此拉取请求的主要变更,即为Portal组件添加CSP nonce支持。
✨ 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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @juno-the-programmer, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the Portal component by integrating Content Security Policy (CSP) nonce support. This crucial update ensures that applications operating under strict CSP rules can effectively utilize the Portal component's scroll locking mechanism without encountering security violations, by providing a mechanism to securely whitelist dynamically injected styles.

Highlights

  • CSP Nonce Support: Introduced a nonce prop to the Portal component to enable Content Security Policy (CSP) compliance for dynamically injected styles, specifically for scroll locking.
  • useScrollLocker Refactor: The useScrollLocker hook was updated to accept an options object, allowing the nonce to be passed. It maintains backward compatibility by still supporting a boolean parameter for existing usages.
  • Comprehensive Testing: Extensive test coverage has been added to validate the nonce functionality, including scenarios for enabling/disabling autoLock, custom containers, and StrictMode.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces Content Security Policy (CSP) nonce support to the Portal component, which is a valuable security enhancement. The changes are well-structured, maintaining backward compatibility for the useScrollLocker hook and including a comprehensive set of tests for the new functionality. I have one suggestion to improve the robustness and readability of the parameter parsing logic in useScrollLocker to prevent a potential runtime error.

Comment on lines +19 to +21
const options = typeof lock === 'object' ? lock : { lock };
const mergedLock = !!(typeof lock === 'boolean' ? lock : options.lock);
const nonce = typeof lock === 'object' ? lock.nonce : undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The current logic for parsing the lock parameter can be simplified for better readability and to handle null values gracefully. Currently, passing null as the lock argument would cause a runtime error because typeof null evaluates to 'object', leading to an attempt to access a property on a null value. This refactoring makes the code more robust and easier to understand.

Suggested change
const options = typeof lock === 'object' ? lock : { lock };
const mergedLock = !!(typeof lock === 'boolean' ? lock : options.lock);
const nonce = typeof lock === 'object' ? lock.nonce : undefined;
const isOptions = typeof lock === 'object' && lock !== null;
const mergedLock = !!(isOptions ? lock.lock : lock);
const nonce = isOptions ? lock.nonce : undefined;

Copy link

@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: 0

🧹 Nitpick comments (1)
src/useScrollLocker.tsx (1)

19-21: 参数处理逻辑正确,但可以简化。

当前的参数规范化逻辑功能正确,兼容布尔值和选项对象两种形式。不过,第 20 行的逻辑稍显冗余,可以简化。

🔎 可选的简化建议

由于第 19 行已经将 options 规范化,第 20 行可以直接使用 options.lock

  const options = typeof lock === 'object' ? lock : { lock };
- const mergedLock = !!(typeof lock === 'boolean' ? lock : options.lock);
+ const mergedLock = !!options.lock;
  const nonce = typeof lock === 'object' ? lock.nonce : undefined;

这样代码更简洁,逻辑更清晰,同时保持相同的功能。

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b5c5fb and 47a5762.

📒 Files selected for processing (3)
  • src/Portal.tsx
  • src/useScrollLocker.tsx
  • tests/index.test.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/Portal.tsx (1)
src/useScrollLocker.tsx (1)
  • useScrollLocker (16-52)
🔇 Additional comments (13)
src/Portal.tsx (3)

43-44: 类型定义和文档清晰准确。

nonce 属性的类型定义正确,且 JSDoc 注释清楚地说明了其用途。


77-77: 属性解构正确。

nonce 从 props 中正确解构。


123-130: 滚动锁定逻辑和 nonce 传递实现正确。

shouldLock 的计算逻辑正确地考虑了所有必要条件(autoLock、open、DOM 可用性、容器类型),并且 nonce 正确地通过对象参数传递给 useScrollLocker。即使 nonce 为 undefined,useScrollLocker 也能正确处理。

src/useScrollLocker.tsx (3)

11-14: 接口定义清晰且类型正确。

UseScrollLockerOptions 接口设计合理,两个可选属性的类型定义准确。


40-42: CSP 选项传递正确。

只在 nonce 存在时才构造 CSP 对象,这种条件构造方式正确且高效,符合 updateCSS API 的预期格式。


51-51: 依赖数组完整且正确。

useLayoutEffect 的依赖数组包含了所有在 effect 中使用的变量(mergedLock、id、nonce),确保在 nonce 变化时能够正确更新样式标签。

tests/index.test.tsx (7)

472-484: 基本 nonce 应用测试正确。

测试用例正确验证了当 autoLock 启用时,nonce 属性被正确应用到样式标签上。断言清晰且符合预期行为。


486-497: 正确测试 autoLock 禁用时的行为。

测试用例验证了当 autoLock 未启用时,即使传入了 nonce,样式标签也不会被创建。这是重要的边界情况。


499-530: 生命周期测试覆盖全面。

测试用例完整验证了 Portal 的打开、关闭和重新打开过程中 nonce 的正确行为,确保样式标签的清理和重建都能正确处理 nonce 属性。


532-548: 自定义容器为 document.body 时的测试正确。

测试用例验证了当通过 getContainer 显式指定 document.body 时,nonce 能够正确应用。这与 Portal 的 shouldLock 逻辑一致。


550-566: 自定义非 body 容器的测试正确。

测试用例正确验证了当渲染到自定义非 body 容器时,不会应用滚动锁定和 nonce。这符合 Portal 的设计逻辑,并且正确清理了测试创建的 DOM 元素。


568-579: 向后兼容性测试重要且正确。

测试用例验证了在不提供 nonce 的情况下,autoLock 功能仍然正常工作。这确保了现有代码的向后兼容性。


581-593: StrictMode 兼容性测试必要且正确。

测试用例验证了在 React StrictMode 下 nonce 功能的正确性。这很重要,因为 StrictMode 会在开发环境中双重调用 effects,确保实现能够正确处理这种行为。

@codecov
Copy link

codecov bot commented Jan 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.67%. Comparing base (8b5c5fb) to head (47a5762).

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #35      +/-   ##
==========================================
+ Coverage   94.57%   94.67%   +0.09%     
==========================================
  Files           7        7              
  Lines         166      169       +3     
  Branches       54       57       +3     
==========================================
+ Hits          157      160       +3     
  Misses          9        9              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@juno-the-programmer
Copy link
Author

@zombieJ please help to review thanks

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.

1 participant