Skip to content

fix(loader): prefer virtualPathResourceMap type over URL extension inference#3035

Open
cptbtptpbcptdtptp wants to merge 6 commits into
dev/2.0from
fix/resource-manager-virtual-type
Open

fix(loader): prefer virtualPathResourceMap type over URL extension inference#3035
cptbtptpbcptdtptp wants to merge 6 commits into
dev/2.0from
fix/resource-manager-virtual-type

Conversation

@cptbtptpbcptdtptp

@cptbtptpbcptdtptp cptbtptpbcptdtptp commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • In _assignDefaultOptions, check _virtualPathResourceMap first for the asset type before falling back to URL extension inference.
  • Ensures editor-registered assets with virtual paths (no file extension) resolve to the correct loader type without requiring the caller to explicitly specify type.

Test plan

  • pnpm run test passes
  • Load an asset by virtual path that has no file extension — should resolve via _virtualPathResourceMap type

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved resource option defaulting and URL/base-URL resolution when remote configuration is present, ensuring asset types and URLs are handled more reliably.
    • Strengthened virtual-path loading so omitted types are correctly inferred.
    • Fixed query-based sub-asset loading so related ?materials[...] variants reuse a single main asset load and apply consistent fallback behavior.
  • Tests
    • Added unit coverage for virtual-path type inference and for single main-load behavior across query-based sub-asset variants.

…ference

When loading an asset by URL, prefer the type registered in
_virtualPathResourceMap over inferring from the URL file extension.
This ensures editor-registered assets with non-standard extensions
(e.g. virtual paths without extensions) resolve to the correct loader.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

ResourceManager refactors type resolution and default-options handling to accept optional remoteConfig and prefer remoteConfig.type, moves item.url defaulting into _loadSingleItem, and simplifies sub-asset query-based loading by removing the assetBaseURL parameter. Tests verify virtual-path type inference and confirm shared main-asset loading across sub-asset query variants.

Changes

ResourceManager type resolution and sub-asset loading

Layer / File(s) Summary
Type resolution and default-options refactoring
packages/core/src/asset/ResourceManager.ts
_assignDefaultOptions now accepts optional remoteConfig and prefers remoteConfig.type when setting unset assetInfo.type. In _loadSingleItem, item.url is defaulted before _assignDefaultOptions is called; remoteConfig lookup happens after parsing the initial URL; base URL resolution and remoteAssetBaseURL derivation follow in sequence.
Sub-asset loading flow wiring
packages/core/src/asset/ResourceManager.ts
Sub-asset query-path loading is rewired to call _loadSubpackageAndMainAsset with reduced parameters, eliminating the prior assetBaseURL argument. _loadMainAsset no longer overwrites item.url; main-asset query-path failures are routed via _onSubAssetFail using remoteAssetBaseURL and queryPath.
Test coverage for type inference and virtual-path loading
tests/src/core/resource/ResourceManager.test.ts
AssetPromise import is added. New virtualPath loading test suite validates type inference from virtualPathResourceMap when loading a virtual path without specifying type, and verifies that multiple sub-asset queries with different ?materials[...] variants invoke the main-asset loader only once.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit rewired the config with grace,
Type resolution in its proper place.
No baseURL passed through the maze,
Virtual paths light up the haze,
Sub-assets share one load to chase! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the main change: prioritizing virtualPathResourceMap type over URL extension inference in the loader logic.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
  • Commit unit tests in branch fix/resource-manager-virtual-type

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

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.16%. Comparing base (97d8d61) to head (89e5b28).
⚠️ Report is 6 commits behind head on dev/2.0.

Additional details and impacted files
@@             Coverage Diff             @@
##           dev/2.0    #3035      +/-   ##
===========================================
+ Coverage    77.31%   79.16%   +1.85%     
===========================================
  Files          914      914              
  Lines       101723   101660      -63     
  Branches     10437    11211     +774     
===========================================
+ Hits         78647    80480    +1833     
+ Misses       22892    20993    -1899     
- Partials       184      187       +3     
Flag Coverage Δ
unittests 79.16% <100.00%> (+1.85%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 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.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/asset/ResourceManager.ts`:
- Around line 343-347: The lookup at line 343 uses the raw assetInfo.url
directly to query _virtualPathResourceMap, which fails to match entries when the
URL contains query parameters like ?q=. Normalize the URL before performing the
_virtualPathResourceMap lookup by extracting the base URL without query
parameters, then use the normalized URL as the key for the lookup while still
preserving the original assetInfo.url for any subsequent operations that need
the full URL.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ec63d091-d98a-4f29-b6bf-49e62f8c41e9

📥 Commits

Reviewing files that changed from the base of the PR and between de75496 and 4cfbcb6.

📒 Files selected for processing (1)
  • packages/core/src/asset/ResourceManager.ts

Comment thread packages/core/src/asset/ResourceManager.ts Outdated
GuoLei1990

This comment was marked as outdated.

Strip the query (?q=) before looking up `_virtualPathResourceMap`, so a
sub-asset virtual path resolves its type the same way `_loadSingleItem`
resolves its path via `assetBaseURL`. Keep explicit `type` taking
precedence over the map (the map only overrides URL-extension inference,
matching the PR title), and guard against an undefined `url` for
urls-only loads such as TextureCube.

Add ResourceManager tests covering extensionless virtual path, sub-asset
query path, and explicit-type precedence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/src/core/resource/ResourceManager.test.ts (1)

91-121: ⚡ Quick win

Add a regression test for url-less LoadItem handling.

These tests validate virtual-path precedence well, but they don’t cover the undefined-url path mentioned in the PR objective. Add one case that passes a LoadItem without url (e.g., urls-only shape) and asserts _assignDefaultOptions does not throw unexpectedly from type inference.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/src/core/resource/ResourceManager.test.ts` around lines 91 - 121, Add a
regression test case within the "assignDefaultOptions virtualPath type" describe
block to cover the url-less LoadItem scenario. Create a new test that calls
_assignDefaultOptions with a LoadItem object that omits the url property (for
example, containing urls instead), then assert that the method does not throw an
error and handles type inference gracefully when url is undefined or missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/asset/ResourceManager.ts`:
- Line 345: The call to ResourceManager._getTypeByUrl(assetInfo.url) at line 345
can execute with an undefined URL in url-list-based inputs, causing a runtime
crash when split is called on undefined before reaching the proper error
handling. Add a guard condition to only call _getTypeByUrl when assetInfo.url is
defined, allowing the assignment to evaluate to undefined and reach the intended
"asset type should be specified" validation path.

---

Nitpick comments:
In `@tests/src/core/resource/ResourceManager.test.ts`:
- Around line 91-121: Add a regression test case within the
"assignDefaultOptions virtualPath type" describe block to cover the url-less
LoadItem scenario. Create a new test that calls _assignDefaultOptions with a
LoadItem object that omits the url property (for example, containing urls
instead), then assert that the method does not throw an error and handles type
inference gracefully when url is undefined or missing.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 587064c4-8119-4061-baef-ad75dee58b78

📥 Commits

Reviewing files that changed from the base of the PR and between 4cfbcb6 and 66d7929.

📒 Files selected for processing (2)
  • packages/core/src/asset/ResourceManager.ts
  • tests/src/core/resource/ResourceManager.test.ts

Comment thread packages/core/src/asset/ResourceManager.ts Outdated
GuoLei1990

This comment was marked as outdated.

…oading

Resolve asset type and remote path from a single _parseURL + virtualPath
lookup, and move baseUrl resolution after the lookup so virtual paths are
no longer polluted by baseUrl. _assignDefaultOptions now takes the resolved
remoteConfig instead of querying the map itself.

- Merge `urls` into `url` before _parseURL — fixes urls-only (TextureCube) throw
- Always strip the `?q=` query from item.url so the sub-asset query no longer
  leaks into the cache key / loadingPromise dedup / request url
- Move virtualPath type checks to the public load() layer (drop tests that
  poked the private _assignDefaultOptions); sync the _parseURL field rename
  in the existing queryPath tests

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
tests/src/core/resource/ResourceManager.test.ts (1)

91-120: 💤 Low value

Consider cleaning up test state to improve isolation.

The tests modify shared state (_virtualPathResourceMap via initVirtualResources) and leave unresolved promises in loadingPromises. While the tests correctly validate the refactored behavior, this could cause flakiness or interference with other tests.

Consider adding cleanup in afterEach or within each test:

Suggested cleanup pattern
+    afterEach(() => {
+      // Clean up virtual path registrations
+      // `@ts-ignore`
+      engine.resourceManager._virtualPathResourceMap = Object.create(null);
+      // `@ts-ignore`  
+      engine.resourceManager._loadingPromises = {};
+    });
+
     it("infers loader type from virtualPathResourceMap when type is omitted", () => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/src/core/resource/ResourceManager.test.ts` around lines 91 - 120, The
tests in the "virtualPath loading" describe block are not cleaning up shared
state after execution, which can cause test interference and flakiness. Add an
afterEach hook within the describe block that clears the virtual resource map
(by calling initVirtualResources with an empty array or resetting
_virtualPathResourceMap) and clears any pending loading promises from
ResourceManager to ensure proper test isolation. Alternatively, add cleanup at
the end of each test (after loaderSpy.mockRestore() calls) to reset the
resourceManager state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/src/core/resource/ResourceManager.test.ts`:
- Around line 91-120: The tests in the "virtualPath loading" describe block are
not cleaning up shared state after execution, which can cause test interference
and flakiness. Add an afterEach hook within the describe block that clears the
virtual resource map (by calling initVirtualResources with an empty array or
resetting _virtualPathResourceMap) and clears any pending loading promises from
ResourceManager to ensure proper test isolation. Alternatively, add cleanup at
the end of each test (after loaderSpy.mockRestore() calls) to reset the
resourceManager state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9cf71b29-ac19-4a28-b5b1-695a6abf9f56

📥 Commits

Reviewing files that changed from the base of the PR and between 66d7929 and e78e08b.

📒 Files selected for processing (2)
  • packages/core/src/asset/ResourceManager.ts
  • tests/src/core/resource/ResourceManager.test.ts

cptbtptpbcptdtptp and others added 2 commits June 16, 2026 16:00
…eturn

- _parseURL returns { assetBaseURL } again — clearer than `url`, which
  collided with the `item.url` reassigned in _loadSingleItem
- _assignDefaultOptions returns void; it mutates in place and the return
  value was no longer used after the lookup moved to the caller

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The added test referenced a non-existent "Texture2D" loader key; the texture
type is AssetType.Texture = "Texture", so vi.spyOn got undefined and threw
"Cannot convert undefined or null to object". Use the AssetType enum for both
loader keys to avoid the typo class.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GuoLei1990

This comment was marked as outdated.

…for type

- _assignDefaultOptions: type ??= ... (was ||=) so an explicit type is only
  defaulted when actually unset, not when it is a falsy string
- add load()-layer tests: urls merged before parse (KTXCube urls-only),
  explicit type wins over the virtualPath map type, and a virtualPath still
  resolves via the map when baseUrl is set

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@GuoLei1990 GuoLei1990 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

总结

第四轮(e78e08bbe → 89e5b2868,3 个 commit)相对上一轮全是收尾打磨,无功能改动:_parseURL 返回字段 url 改名 assetBaseURL(消除与 _loadSingleItem 里被重赋值的 item.url 的命名碰撞,并与 _onSubAssetSuccess/_onSubAssetFail 已有的 assetBaseURL 形参命名对齐)、_assignDefaultOptions 返回值改 void(查表搬到调用方后该返回值已无人消费)、||=??=、补 4 个 load() 层测试。逐项核对均为等价 / 纯净化改动,无回归。可以合。

上轮问题状态

  • [P2] 虚拟路径查表用未解析原始 url — ✅ 上一轮已解决(_parseURL 先于查表跑),本轮无变动,保持关闭。
  • CodeRabbit「_getTypeByUrl(undefined) crash」/「normalize url before lookup」 — ✅ 已结构化兜住(item.url ?? item.urls.join(",") 前置补齐 + _parseURL 剥 query),CodeRabbit 自己也标了 "Addressed in e78e08b / 66d7929",保持关闭。
  • [P3] shares the main asset across sub-asset queries 是 characterization 非回归 — 上轮已记,本轮无变动;本轮新增的 merges urls into a single url before parsing 属同一类——base 上 _assignDefaultOptions 早就有 assetInfo.url ?? assetInfo.urls.join(",")(base :350,在 _parseURL 之前),KTXCube urls-only 在 base/PR 行为一致,这条测试 base 同样 pass,是既有行为的 characterization。无害,归入同一条 P3,不另起新问题。
  • ||=??= — 上轮我已就 ||=type:"" 当未设处理这点表态"不是问题"。本轮翻成 ??=。逐查 AssetType 全部为非空串、且公开 API type?: AssetType 构造不出 "",两种写法仅在 type==="" 这一不可达分支发散,均非真实路径,不再就此发散。

关键核对(确认无回归)

  • 字段改名 url → assetBaseURL_parseURL 唯一消费点 :356 同步解构,数据流 1:1 不变,纯命名一致性改进。
  • _assignDefaultOptions 返回 void:唯一调用点 :361 不使用返回值,确为死返回值清除。
  • 新增 4 测试:均经公开 load() 入口触发、spy _loaders 断言公开输出(type / call count),是链路测试不戳私有;@ts-ignore 仅用于访问静态 _loaders map,与本文件既有测试(:21/:42/:50/:58/:67)同一惯例。

问题

无新问题。本轮 delta 全是命名 / 死代码 / 测试覆盖的收尾打磨,前序问题已全部闭环。

简化建议

无。代码已是上一轮本质解的精简形态,本轮进一步收紧了命名与返回签名,干净。

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