Align RefreshSig with React HOC-chain design; make sign idempotent#613
Merged
JoviDeCroock merged 2 commits intomainfrom Apr 15, 2026
Merged
Align RefreshSig with React HOC-chain design; make sign idempotent#613JoviDeCroock merged 2 commits intomainfrom
JoviDeCroock merged 2 commits intomainfrom
Conversation
Both Babel and Oxc emit _s(memo(_c = _s(inner, key)), key) for memo-wrapped components. The status-machine in the old $RefreshSig$ would call sign with 'needsHooks' on the outer type before it had been registered, crashing with "Cannot set properties of undefined". New $RefreshSig$ implementation mirrors createSignatureFunctionForTransform from vite-plugin-react: use `typeof key === 'string'` to discriminate keyed vs body calls, always pass 'begin' for keyed calls regardless of chain depth, and collect hooks once via a didCollectHooks flag on the first body call. sign() in @prefresh/core is made idempotent on the 'begin' path (won't overwrite an inner type's getCustomHooks with an outer HOC call's undefined) and guards the 'needsHooks' path against a missing signature. Adds unit tests for $RefreshSig$ covering single components, memo-wrapped HOC chains, and the one-shot hook collection guarantee, and wires package unit tests into the GitHub Actions workflow. Fixes #610
🦋 Changeset detectedLatest commit: 22f53f5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
…m into block comments)
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.
Problem
Fixes #610.
Both Babel and Oxc emit two keyed
_scalls for amemo-wrapped component:The previous
$RefreshSig$used astatusstate machine. After the inner call,statusbecame'needsHooks'. When the outer call arrived,signwas invoked with'needsHooks'on a type that had not been registered yet — crashing with "Cannot set properties of undefined".The earlier patch (
key ? 'begin' : status) stopped the crash, but the underlying design was still fragile: a mutable status variable threading through an HOC chain it was never designed for.Solution
Align with
createSignatureFunctionForTransformfromvite-plugin-react/packages/common/refresh-runtime.js, which was explicitly designed for HOC chains:statustypeof key === 'string''begin', regardless of chain depth'needsHooks'statusdidCollectHooksone-shot flag on body callsignis now idempotent@prefresh/core'ssignis also hardened:'begin'path: skip if signature already exists (preserves innergetCustomHooks)'needsHooks'path: guard against missing signature entryTests
5 new unit tests in
packages/vite/test/refreshSig.test.mjscovering:getCustomHooksnot overwritten by outer HOC call)Package unit tests (vite + rolldown) are now wired into the GitHub Actions workflow.