fix(plugin-vue): isolate ssr and client descriptor state (fix #764)#765
Open
seanogdev wants to merge 1 commit into
Open
fix(plugin-vue): isolate ssr and client descriptor state (fix #764)#765seanogdev wants to merge 1 commit into
seanogdev wants to merge 1 commit into
Conversation
The descriptor cache was keyed by filename only. `compileScript` mutates the descriptor (and its script/scriptSetup blocks) with ssr-specific compiled state, so sharing the same descriptor object between an ssr pass and a subsequent client pass poisoned the client output — most visibly, `<script setup>` imports that were only referenced from the template got dropped from `__returned__`, causing runtime `$setup.<Component> is not a function` errors. Two fixes are needed because there are two layers of sharing: 1. Key our own descriptor cache by `(filename, ssr)` so the main and sub-block transforms look up distinct entries for each mode. The `prevCache` (HMR diffing only) stays filename-keyed. 2. Clone the descriptor returned from `compiler.parse`. `parse` is backed by an internal LRU cache keyed by source, so even with distinct cache entries both keys pointed at the same object. Cloning the descriptor and its script/scriptSetup/template/style blocks gives each cached entry an object `compileScript` is free to mutate. Adds a regression test covering the exact Vitest flow from vitest-dev/vitest#9855.
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.
Description
Fixes the descriptor-cache poisoning described in #764.
packages/plugin-vue/src/utils/descriptorCache.tskeys its descriptor cache by filename only, andvue/compiler-sfc'sparseCachereturns the sameSFCDescriptorobject for the same source.compileScriptmutates that descriptor with ssr-specific compiled state, so an ssr transform followed by a client transform of the same SFC produces a<script setup>whose__returned__omits template-only imports. The rendered component then throws$setup.<Component> is not a function.This PR:
cache,hmrCache) by(filename, ssr)via a composite string key.ssris threaded throughcreateDescriptor,getDescriptor,invalidateDescriptor, and theload/transformsub-block handlers (which already hadssrin scope fromopt.ssr).prevCache(HMR diffing) stays filename-keyed because HMR is client-only.compiler.parse(shallow spread plus shallow clones ofscript,scriptSetup,template,styles,customBlocks). Step (1) alone is insufficient becauseparseCachereturns the same descriptor for the same source regardless of our cache key — the clone gives each cache entry an objectcompileScriptcan safely mutate.invalidateScriptandhandleHotUpdateto invalidate both ssr/client entries (newpeekCachedDescriptor/setCachedDescriptorhelpers).?src=descriptors (setSrcDescriptor/getSrcDescriptor) filename-keyed — they're only consumed by the style transform, never bycompileScript.Adds a regression test
__tests__/ssr-then-client-cache.spec.tsthat:transformMain+resolveScriptAdditional context
Symptom was first reported as vitest-dev/vitest#9855 because Vitest's
relatedcommand surfaces it via cross-project SSR dependency analysis, but the bug is plugin-vue's — any ssr→client transform order on the same SFC reproduces it.Verified downstream by re-running the teamwork.com monorepo's
pnpm test related $files(the command that was failing on our branch) against a linked build of this branch: 3 previously-failing storybook tests now pass, 120/120 total — with no changes to the consuming component (the<script setup>const workaround was reverted before the run).What is the purpose of this pull request?
Before submitting the PR, please make sure you do the following
fixes #764).