fix(compositor): PR #170's asset-path fix was a no-op in the packaged app — bypass asar-transparent fs#171
Merged
Conversation
…or real asset files `resolveSceneAssetPath`'s candidate-probe loop (from the previous commit) used plain `fs.existsSync`, which Electron patches to read *through* an asar archive — from JS's point of view, `.../app.asar/dist/wallpapers/x.jpg` "exists". So the probe locked onto the VITE_PUBLIC candidate (pointing into the asar) on every call and never reached the real `resourcesPath` files, making the previous fix a no-op in the actual packaged app: rebuilt and relaunched it, and the exact same "wallpaper image ... introuvable" errors came right back. Confirmed the mechanism by running a probe script inside the packaged binary via `ELECTRON_RUN_AS_NODE=1`: patched `fs.existsSync` on the asar-internal path answered `true`; the native addon (raw `fopen`/`CreateFile`, no knowledge of asar) still gets ENOENT on that same path. `original-fs` is Electron's own escape hatch for this — same API, unpatched. Route the existence check through it, falling back to plain `fs` where `original-fs` doesn't exist (outside Electron, i.e. the vitest suite), since plain Node's `fs` was never patched in the first place there. Re-verified live after rebuilding: the same project's bundled wallpaper and themed cursor sprite now render in the packaged app, and the "introuvable"/ENOENT log lines are gone.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fast-follow on #170 (already merged). Rebuilt and relaunched the packaged app to visually confirm that fix, and the exact same bug came right back: a bundled wallpaper still rendered as a flat colour, a themed cursor still fell back to default art, and the main-process log still showed
— the exact path #170 was supposed to stop sending.
Root cause
resolveSceneAssetPath's candidate-probe loop used plainfs.existsSync. Electron patchesfsto read through an asar archive transparently — from JS's point of view,.../app.asar/dist/wallpapers/wallpaper5.jpg"exists". So the probe locked onto the first candidate (VITE_PUBLIC, pointing into the asar) on every single call and never reached the second, real one (resourcesPath). #170's fix compiled correctly, shipped correctly, and never actually resolved anything, because the existence check itself was lying.Confirmed the mechanism directly rather than guessing: ran a probe script inside the packaged binary via
ELECTRON_RUN_AS_NODE=1.The native addon calls raw
fopen/CreateFilewith no concept of asar, so it agrees withoriginal-fs, not with patchedfs— which is exactly why the wrong candidate kept winning.Fix
original-fsis Electron's own escape hatch for precisely this: same API, unpatched. Route the existence check through it, falling back to plainfswhereoriginal-fsdoesn't exist — outside Electron, i.e. the vitest suite, where plain Node'sfswas never patched in the first place, so no fallback behavior changes.Verification
tsc && vite build && electron-builder, native addon unchanged), grepped the packagedapp.asarbytes directly to confirmrealExistsSync/original-fsactually compiled in.[compositor] wallpaper image ... introuvablelog line is gone.tsc --noEmitclean, biome clean, existing 15 tests incompositorViewService.test.tsstill pass (they run under plain Node, so they exercise thefsfallback branch, not the asar-bypass itself — that half is Electron-runtime-specific and is what the live verification above covers).Note for review
I did not add a mocked unit test simulating Electron's asar-fs patching — a test that only asserts
localRequire("original-fs")gets called would be closer to tautological than to a real regression guard, since the actual failure mode (patchedfs.existsSynclying about an asar-internal path) can't be faithfully reproduced outside a real Electron + real asar. The live verification above is the real check for this one.