fix(ssr): register export * getters next to earlier same-source import to fix cyclic facade namespace#22493
Open
schiller-manuel wants to merge 1 commit into
Open
fix(ssr): register export * getters next to earlier same-source import to fix cyclic facade namespace#22493schiller-manuel wants to merge 1 commit into
schiller-manuel wants to merge 1 commit into
Conversation
…t to fix cyclic facade namespace
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.
Fixes #22491.
Fix
Transform-level change in
ssrTransform.ts. Whenexport * from 'x'reuses a source already imported earlier in the same module:sourceToImportMap).export *.__vite_ssr_exportAll__(existingImportId)immediately after the earlier import (vias.appendLeft(existingImport.end, ...)).export *statement.appendLeftfor those nodes via anearlyExportAllDeclarationsSet to avoid double-emission.!node.exported, soexport * as ns from 'x'is left untouched.This restores link-time
export *semantics for the common facade pattern: the wildcard getters are registered before any subsequent cycle-triggering import awaits.Tests
runtime/__tests__/fixtures/cyclic-reexport-facade/*— fixtures mirroring the reduced repro in the issue.server-runtime.spec.ts > resolves export star bindings through a cyclic facade— fails onmainwithTypeError: createThing is not a function, passes with this patch.ssrTransform.spec.ts— three inline-snapshot testsScope (in this PR)
Only
export * from 'x'where'x'was already imported earlier in the same module (import …orexport … from). The reported real-world case (TanStack Start) matches this shape.Out of scope (can extend if maintainers want)
These are adjacent cyclic-
export *deviations from spec link-time semantics that this PR does not address, to keep the diff minimal:1. No prior same-source import
Both the hoisted
__vite_ssr_import__("./core.js")and its__vite_ssr_exportAll__end up after the./client.jsimport in the hoisted block, so the cycle observes the facade beforecore's wildcard is registered. A fix would hoist plainexport *imports ahead of any cycle-capable preceding import, but that requires broader reordering.2. Cycle during the anchor import's own await
The patched
__vite_ssr_exportAll__(x)is appended after the anchor import resolves. While we're still awaiting./x.js, the facade namespace does not yet have the wildcard getters. A fix would need to registerexportAllbefore awaiting the anchor — but at that point the imported module reference does not exist yet, so it requires a different runtime shape (e.g. a deferred-getter proxy).3. Multiple
export *from the same anchored sourceBoth deduped
export *statements emit__vite_ssr_exportAll__(__vite_ssr_import_0__)at the same anchor — idempotent at runtime, but redundant. Trivially dedupable with a per-anchorSet<sourceValue>if desired.4.
export * as nsis left at its textual positionA more general fix could also hoist the
nsnamed-export registration next to the anchor import, butexport * as nsis a namespace snapshot with different semantics fromexport *and is not in the reported failure mode.