Repository navigation
Share one dynamic slot among props on one CSS property - #191
Merged
Merged
Conversation
Props alike in the properties they write, the current variable and the transform, such as `h` and `height`, now share one slot variable, one slot rule per condition and one registration. Each takes the slot of the first by name; its runtime metadata keeps its own scale and transform. When one element sets two of them, the later-defined prop's write wins and the earlier one's class leaves with it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Three units in each mode lose the slots of seven merged groups: 42 slot rules and their 42 registrations, with nothing added and every kept rule in its order. In dynamicPropsJson the seven merged props point at the shared slot, and no other field changes. The seam battery is unchanged. The checked intent names the change, and each drift was registered at its exact hashes for the refresh only. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Props that write the same CSS property the same way, such as
handheight, now share one dynamic slot: one slot variable, one slot rule per condition, and one@propertyregistration per variable. vite-app drops from 268 slot rules to 232.This is board ticket
props-on-one-css-property-share-one-slot, lever 2 of the user's three dynamic-slot reductions. It matches rank 3 of the dynamic-values survey: share aliases after the property is resolved, but keep conditions, transforms, multiple outputs and real shorthands apart.Contract
Grouping. Value props share a slot when they agree on all three:
properties, or elseproperty);currentVarit also sets;So
pandptnever share,handheightdo, andsize(width and height) shares only with a prop that writes the same pair. Declaration props are unchanged.Naming. A group takes the slot of its first member by name:
handheightboth useanimus-dyn-h_and--animus-h_. This applies to system props, and to each component's custom props, which keep their component hash.Runtime metadata. Each prop keeps its own entry, with its own scale, transform, strict flag and keywords. Only
varNameandslotClasspoint at the shared slot.Precedence (root's answer, from the user: option a). When one element sets two props of a group, the later-defined prop wins, in
systemPropNamesorder. JSX order does not matter.resolveClassesalready walks props in that order. The later write replaces the earlier one's variable, and the earlier class that reads that variable leaves with it: the slot class or its--keeptwin, at the base and at each breakpoint. So the element never carries a--keepclass that disagrees with the value.Scope
one-elements-props-on-one-css-property-resolve-in-prop-order, which follows the same rule.animus-u-*rules sort afteranimus-dyn-*.The change
extract-v2/src/dynamic_meta.rsValuePropMeta::slot_key: destination,currentVarand transform.share_slots: points each prop in a group at the first member's slot.extract-v2/src/analyze_css.rscallsshare_slotsfor the system props and for each component's custom props, before the slot rules are built.extract-v2/src/css.rs:build_variable_slot_entriesrenders a shared slot once. Register dynamic slot variables as non-inheriting #189's registrations already dedupe by variable name, so each remaining variable gets exactly one.system/src/runtime/resolveClasses.ts: when a later-defined prop writes an already-written slot variable, it replaces the earlier write and removes the earlier class that read it. It needs no allocation; the check is anintest on the staged style object.Proof (run-and-discard, not committed)
Counts (built e2e output; main 9e35d18 vs this branch). A slot is a base slot class; slot rules include each breakpoint's rule; runtime metadata is the delivered dynamic-prop config.
h/height,w/width,minH/minHeight,maxH/maxHeight,minW/minWidth,maxW/maxWidth,pos/position,flexDir/flexDirectionandarea/gridArea.Unchanged computed styles.
{ _, sm }value.height,position,gridArea, …) because its slot rule sorted later. The branch gives the later-defined alias, in either JSX order, as decided.--keepprobe. A scratch probe with two shared props carrying acurrentVarchecked the--keephandling. The winning prop's--keepor plain class replaced the other's at the base and atsm.Runtime cost.
resolveClasseswas run 10⁶ times per case, with medians of 8 interleaved rounds under bun:These are within noise. A first version that tracked writes in a per-call
Mapcost +2.5% to +6%, so it was replaced.Retained case (one)
packages/_integration/__tests__/shared-prop-slots.test.ts, "props on one property with one transform share a slot; the later-defined prop wins". It pins the contract:handheight(one transform) share a slot;rawH(no transform) keeps its own;--animus-h_-smis registered once;{ height, h }and{ h, height }both resolve toh's value with one slot class.Against main's engine:
That run predates the precedence correction, which renamed the test. The assertion that failed is unchanged. With this change it passes. The neighbouring slot tests (
runtime-current-var,slot-variable-registration, and the system runtime tests) pass 59/59.Checks
vp run verify:lintexited 0 locally before each push, and CI made the first run of the other rows.Parity refresh (
shared-dynamic-slots-20261009, second commit). CI's first run failed only the parity row, as expected. Locally, three of 66 units changed, the same in both modes:extract-all,extract/system-props.tsxandintegration/system-props.tsx. In each:@propertyregistrations removed.dynamicPropsJson: seven props (height,width,minHeight,maxHeight,minWidth,maxWidth,gridArea) point at the shared slot. Every entry stays, and no other field changes.The eight drifts were registered at their exact hashes as
intentional-correctnessfor the refresh only, and the register is empty again. After the refresh,vp run verify:paritypasses: 66/66 units in both modes, seam battery 29/29.Oracle. The oracle's
bySlotClassattributes a shared slot rule to one of its props, as it already does for a utility class two props share.I'll report the CI result to root.
Independent review: not launched (root arranges review).
🤖 Generated with Claude Code