Skip to content

Conversation

@Adamlyu-hub
Copy link
Contributor

@Adamlyu-hub Adamlyu-hub commented Aug 8, 2025

这个 PR 做了什么? (简要描述所做更改)
解决Windows开发环境中Taro.request、Taro.setStorageSync、Taro.getStorageSync、Taro.showToast等API方法不可用的问题。核心原因在于Windows系统路径使用反斜杠(\)而非正斜杠(/),同时路径中可能存在空格字符,导致相关模块无法被正确识别和导入。

这个 PR 是什么类型? (至少选择一个)

  • [ ✅] 错误修复 (Bugfix) issue: fix #
  • 新功能 (Feature)
  • 代码重构 (Refactor)
  • TypeScript 类型定义修改 (Types)
  • 文档修改 (Docs)
  • 代码风格更新 (Code style update)
  • 构建优化 (Chore)
  • 其他,请描述 (Other, please describe):

这个 PR 涉及以下平台:

  • 所有平台
  • [ ✅] Web 端(H5)
  • 移动端(React-Native)
  • 鸿蒙(Harmony)
  • 鸿蒙容器(Harmony Hybrid)
  • ASCF 元服务
  • 快应用(QuickApp)
  • 所有小程序
  • 微信小程序
  • 企业微信小程序
  • 京东小程序
  • 百度小程序
  • 支付宝小程序
  • 支付宝 IOT 小程序
  • 钉钉小程序
  • QQ 小程序
  • 飞书小程序
  • 快手小程序
  • 头条小程序

Summary by CodeRabbit

  • 修复问题
    • 统一并规范化构建/转换时的路径格式(处理前导字符、查询参数与分隔符等差异),提升跨平台兼容性,减少因路径格式不一致导致的转换或构建失败的潜在问题。

@coderabbitai
Copy link

coderabbitai bot commented Aug 8, 2025

Walkthrough

本次变更在 Vite 配置的 apiPlugin 中对 transform 函数进行了调整:在判断前对传入的 idsourceDir 做路径规范化(移除前导 \u0000、去掉查询参数、统一斜杠),然后基于规范化路径进行 startsWith 检查,再决定是否应用 Babel 转换。

Changes

Cohort / File(s) Change Summary
Vite 插件路径处理优化
packages/taro-platform-h5/src/program.ts
apiPlugintransform 中新增对 id 的规范化流程(去前导空字符、剥离查询、统一斜杠),并对 sourceDir 做斜杠规范化,使用规范化值进行 startsWith 判断后再执行 Babel transform。

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Vite as Vite / Plugin
    participant Transform as transform(id)
    participant Norm as normalizePath
    participant Check as conditionCheck
    participant Babel as Babel.transform

    Vite->>Transform: 调用 transform(id)
    Transform->>Norm: 去除前导 \u0000、剥离 ?query、替换 "\" -> "/"
    Transform->>Norm: 同步规范化 viteCompilerContext.sourceDir
    Norm-->>Transform: 返回 cleanId, normalizedSourceDir
    Transform->>Check: 使用 cleanId.startsWith(normalizedSourceDir) && ext check(原 id 的扩展名判断)
    alt 条件成立
        Transform->>Babel: 调用 Babel.transform(cleanId)
        Babel-->>Transform: 返回变换结果
    else 不满足
        Transform-->>Vite: 跳过处理,返回 null
    end
Loading

Estimated code review effort

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

Poem

兔子叼着小斜杠,
路径清洁步轻扬。
前导空与问号去,
跨平台不再迷茫。
代码整齐心欢畅 🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai bot requested review from Single-Dancer and tutuxxx August 8, 2025 08:11
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: 2

🧹 Nitpick comments (2)
packages/taro-platform-h5/src/program.ts (2)

233-236: 可选:同时将 Babel transform 的 filename 切换为 cleanId

为避免 filename 携带查询参数或反斜杠导致的映射异常,建议将 transformAsync 的 filename 设置为 cleanId(非必需,但更一致):

// 下面代码在当前 if 分支内:
// 建议将
// filename: id,
// 改为
filename: cleanId,

说明:这项改动不在本变更行内,实现时请在 238-246 行对应的 transformAsync 调用处调整。


233-235: 可选:兼容 Vite 的 /@fs/ 与 file:// 前缀

在某些场景(特别是跨根目录或依赖解析)Vite 的模块 id 可能以 /@fs/ 或 file:// 开头。为进一步增强稳健性,可在清洗阶段顺便处理:

if (cleanId.startsWith('/@fs/')) {
  cleanId = cleanId.slice('/@fs/'.length)
}
// 如需支持 file:// URL,可配合 node:url:
/*
import { fileURLToPath } from 'node:url'
if (cleanId.startsWith('file://')) {
  try { cleanId = fileURLToPath(cleanId) } catch {}
}
*/

注:这是增强项,当前修复不依赖此改动。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb41575 and a9e6354.

📒 Files selected for processing (1)
  • packages/taro-platform-h5/src/program.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: ianzone
PR: NervJS/taro#17993
File: .github/advanced-issue-labeler.yml:20-63
Timestamp: 2025-07-11T14:04:05.557Z
Learning: 在 NervJS/taro 项目的 .github/advanced-issue-labeler.yml 中,平台标签被设计为可以多个共存。当用户选择"所有平台"时,系统会同时应用多个平台标签(如 T-h5, T-rn, T-weapp 等),这是期望的行为而非冲突。同样,"所有小程序"也会为小程序相关的标签应用多个标签。这种设计有助于跨平台问题的管理和维护者关注。
📚 Learning: 2025-08-08T02:32:58.207Z
Learnt from: ianzone
PR: NervJS/taro#18146
File: packages/babel-plugin-transform-react-jsx-to-rn-stylesheet/package.json:12-14
Timestamp: 2025-08-08T02:32:58.207Z
Learning: 在 Taro 项目的 pnpm 工作区中,Vitest 相关依赖(vitest 和 vitest/coverage-istanbul)被管理在根目录的 package.json 中,而不是各个子包的 devDependencies 中。这是 monorepo 中依赖提升的标准做法。

Applied to files:

  • packages/taro-platform-h5/src/program.ts
📚 Learning: 2025-05-25T18:02:31.387Z
Learnt from: ianzone
PR: NervJS/taro#17746
File: packages/taro-runtime/tsdown.config.ts:10-16
Timestamp: 2025-05-25T18:02:31.387Z
Learning: 在 taro-runtime 包的 tsdown 配置中,必须禁用 treeshake 来保留 dom-external/index.js 文件。

Applied to files:

  • packages/taro-platform-h5/src/program.ts
🧬 Code Graph Analysis (1)
packages/taro-platform-h5/src/program.ts (1)
packages/taro-vite-runner/src/harmony/babel.ts (1)
  • viteCompilerContext (9-94)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build Rust Binding / stable - x86_64-apple-darwin
  • GitHub Check: Build Rust Binding / stable - x86_64-pc-windows-msvc
🔇 Additional comments (1)
packages/taro-platform-h5/src/program.ts (1)

227-235: 路径规范化与清洗方向正确,能有效修复 Windows 上的识别问题

  • 去除前导 NUL 字符、剥离查询参数、统一分隔符为正斜杠,以及对 sourceDir 做同样处理,都是必要步骤,思路到位。

Comment on lines +233 to +236
cleanId = cleanId.split('?')[0].replace(/\\/g, '/') // 👈 替换斜杠方向

const normalizedSourceDir = viteCompilerContext.sourceDir.replace(/\\/g, '/') // 👈 替换斜杠方向
if (cleanId.startsWith(normalizedSourceDir) && exts.some((ext) => id.includes(ext))) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

用路径边界判断与基于 cleanId 的后缀匹配,避免误判与平台差异

当前仍然存在两处潜在问题:

  • 目录前缀误判:cleanId.startsWith(normalizedSourceDir) 在 sourceDir 是另一路径前缀时会误命中(如 C:/src 与 C:/src2)。
  • 扩展名匹配:仍用原始 id.includes(ext) 且为包含匹配,可能出现误判;亦未与上面的 cleanId 清洗保持一致。

建议在本段内改为“边界安全的目录判断 + 基于 cleanId 的结尾扩展匹配”,示例 diff 如下:

-              cleanId = cleanId.split('?')[0].replace(/\\/g, '/') // 👈 替换斜杠方向
+              // 统一斜杠并去掉查询参数,便于跨平台匹配
+              cleanId = cleanId.split('?')[0].replace(/\\/g, '/')

-              const normalizedSourceDir = viteCompilerContext.sourceDir.replace(/\\/g, '/') // 👈 替换斜杠方向
-              if (cleanId.startsWith(normalizedSourceDir) && exts.some((ext) => id.includes(ext))) {
+              // 统一 sourceDir,并确保以路径边界比较,避免前缀相似导致的误命中
+              const normalizedSourceDir = viteCompilerContext.sourceDir.replace(/\\/g, '/').replace(/\/+$/, '')
+              const inSource = cleanId === normalizedSourceDir || cleanId.startsWith(normalizedSourceDir + '/')
+
+              // 更稳健的扩展名判断:基于 cleanId 且只匹配结尾
+              const extsPattern = new RegExp(`\\.(?:${exts.map((e: string) => e.replace(/^\\./, '')).join('|')})$`, 'i')
+
+              if (inSource && extsPattern.test(cleanId)) {

这样可同时解决:

  • Windows 路径前缀误匹配;
  • 查询参数与分隔符已清洗,扩展名判断与之保持一致;
  • 降低 includes 带来的误匹配风险。
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cleanId = cleanId.split('?')[0].replace(/\\/g, '/') // 👈 替换斜杠方向
const normalizedSourceDir = viteCompilerContext.sourceDir.replace(/\\/g, '/') // 👈 替换斜杠方向
if (cleanId.startsWith(normalizedSourceDir) && exts.some((ext) => id.includes(ext))) {
// 统一斜杠并去掉查询参数,便于跨平台匹配
cleanId = cleanId.split('?')[0].replace(/\\/g, '/')
// 统一 sourceDir,并确保以路径边界比较,避免前缀相似导致的误命中
const normalizedSourceDir = viteCompilerContext.sourceDir
.replace(/\\/g, '/')
.replace(/\/+$/, '')
const inSource =
cleanId === normalizedSourceDir ||
cleanId.startsWith(normalizedSourceDir + '/')
// 更稳健的扩展名判断:基于 cleanId 且只匹配结尾
const extsPattern = new RegExp(
`\\.(?:${exts
.map((e: string) => e.replace(/^\./, ''))
.join('|')})$`,
'i'
)
if (inSource && extsPattern.test(cleanId)) {
🤖 Prompt for AI Agents
In packages/taro-platform-h5/src/program.ts around lines 233 to 236, the current
check using cleanId.startsWith(normalizedSourceDir) can cause false positives
when sourceDir is a prefix of another path, and the extension check uses
id.includes(ext) which is an imprecise substring match. To fix this, replace the
startsWith check with a boundary-safe directory comparison (e.g., ensure the
character after normalizedSourceDir in cleanId is a path separator or the string
ends) and change the extension check to use cleanId.endsWith(ext) to accurately
match file extensions after cleaning the path. This ensures correct path prefix
matching and precise extension validation.

💡 Verification agent

🧩 Analysis chain

建议对全仓库同类判定做一致性巡检

为避免类似 Windows 路径问题在其它插件/分支重复出现,建议巡检是否还有基于 id.startsWith(sourceDir) 的直接字符串比较,并统一采用“清洗 + 路径边界 + 扩展名后缀”的写法。

可用以下脚本在仓库检索潜在位置,人工复核是否需要采用同样规范化处理:


🏁 Script executed:

#!/bin/bash
# 搜索基于 sourceDir 的 startsWith 判定
rg -n --no-heading "startsWith\\(.*sourceDir" -A 2 -B 2

# 搜索对 id 的扩展名 includes 判定
rg -n --no-heading "exts\\.some\\(.*id\\.includes\\(" -A 2 -B 2

# 搜索 Vite 插件 transform 中对 id 的处理(便于发现未清洗的地方)
rg -n --no-heading "async?\\s+transform\\s*\\(code,\\s*id\\)" -A 20 -B 2

Length of output: 6180


统一路径前缀匹配时的清洗及后缀校验
为避免 Windows 下反斜杠和 query 参数导致匹配失效,全仓库所有基于 sourceDirstartsWith 判定都应按以下流程处理:

  1. 去除特殊前缀(如 \u0000)和 ? 及后续参数
  2. 将所有 \ 统一替换为 /
  3. 使用清洗后的路径做 startsWith(normalizedSourceDir),并尽量结合路径边界(如 normalizedSourceDir + '/'
  4. 再做扩展名后缀过滤(exts.some(ext => cleanId.endsWith(ext))

以下位置需同样引入该规范化处理:

  • packages/taro-vite-runner/src/harmony/babel.ts(transform 钩子中对 id.startsWith(viteCompilerContext.sourceDir) 及后续 exts.some(id.includes)
  • packages/taro-vite-runner/src/h5/config.ts(entryFileNames 中对 facadeModuleId.startsWith(sourceDir) 的判断)
  • (packages/taro-platform-h5/src/program.ts 已按规范处理,无需改动)

可用脚本复核并定位所有潜在场景:

rg -n --no-heading "startsWith\\(.*sourceDir" -A2 -B2
rg -n --no-heading "facadeModuleId\\?\\.startsWith" -A2 -B2
🤖 Prompt for AI Agents
In packages/taro-vite-runner/src/harmony/babel.ts and
packages/taro-vite-runner/src/h5/config.ts, locate all instances where sourceDir
is used with startsWith for path prefix matching and ensure the following
normalization steps are applied: first remove special prefixes like \u0000 and
query parameters starting with '?', then replace all backslashes '\' with
forward slashes '/', and use the cleaned path for startsWith checks combined
with a trailing '/' to ensure path boundary correctness. After that, perform
extension suffix filtering using endsWith on the cleaned path. This will align
these files with the normalization approach already implemented in
packages/taro-platform-h5/src/program.ts.

@codecov
Copy link

codecov bot commented Aug 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 55.06%. Comparing base (52ceb74) to head (5c4a7dc).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##             main   #18153    +/-   ##
========================================
  Coverage   55.06%   55.06%            
========================================
  Files         416      416            
  Lines       21563    21563            
  Branches     5285     5289     +4     
========================================
  Hits        11873    11873            
- Misses       8038     8173   +135     
+ Partials     1652     1517   -135     
Flag Coverage Δ
taro-cli 72.85% <ø> (ø)
taro-runtime 59.87% <ø> (ø)
taro-web 53.13% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 44 files with indirect coverage changes

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

This was referenced Aug 9, 2025
@Single-Dancer Single-Dancer merged commit 58b83f4 into NervJS:main Aug 30, 2025
24 checks passed
@Single-Dancer Single-Dancer added this to the 4.1.6 milestone Aug 30, 2025
This was referenced Sep 6, 2025
@coderabbitai coderabbitai bot mentioned this pull request Sep 11, 2025
25 tasks
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