Skip to content

signals: omit()'s copy path re-homes accessors with the source as receiver - #3544

Open
ryansolid wants to merge 1 commit into
nextfrom
fix/omit-fallback-read-through
Open

ryansolid wants to merge 1 commit into
nextfrom
fix/omit-fallback-read-through

Conversation

@ryansolid

Copy link
Copy Markdown
Member

Summary

omit()'s no-Proxy copy path forwarded accessor descriptors as-is onto the copy. merge()'s copy path, three functions above it, already binds a copied getter to its source. Both now follow the same rule: a prop's getter is defined only for a read through its own object.

This is groundwork for #3511 (finding 2). The server-side props emission under evaluation there builds each component's props with a per-site constructor whose getters are shared across instances and read their state off this — the thing that gets the object out of V8 dictionary mode (15–48% SSR CPU on the component-heavy yak-bench cases). A descriptor forwarded from such an object and read on another throws. Nothing in core reads props that way except this one fallback branch, which cannot execute on a server runtime anyway; it is fixed here so the rule holds everywhere.

Changes

  • omit() no-Proxy path: accessors are re-homed (get/set bound to the source, configurable: true), matching merge(). Data descriptors are unchanged.
  • The rule is written down on merge()'s doc block.
  • isStatic()'s note on server/client parity now says what is actually equal — the own descriptors — rather than "the compiled shape".
  • Test (utilities-no-proxy.test.ts): a props object in the receiver-dependent shape (plain prototype, shared getter reading this[$m]); the forwarded descriptor throws, omit/merge copies read live through the source and keep accessor kind. Fails on omit without the fix.

Not changed

Stores (createStore source clone, storePath merge) also copy descriptors, deliberately: a store getter is re-homed so it computes against the store proxy. That is the store's own contract, and a compiled props object is not a store source. Left as is; noted so it is a decision rather than an omission.

Ecosystem

Surveyed for descriptor forwarding of props: Kobalte solid2, corvu, ark (solid), solid-ui, solid-primitives solid2 — none (solid-primitives' mutable already binds). @yak/solid's copyProps does forward; its fix is a getter that reads through props, and the note goes to them with the compiler PR.

Made with Cursor

…eiver

A prop's getter is defined only for a read through its own object. The
plain-object merge() path already binds a copied getter to its source;
omit()'s no-Proxy path forwarded the descriptor as-is, so a getter that
keeps state on the instance (the compiler's server props, #3511) would
throw on the first read of the copy. Both copy paths now follow the
same rule, the rule is written down on merge(), and isStatic()'s note
about server/client parity says what is actually equal: the descriptors.

Co-authored-by: Claude via Cursor <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot

changeset-bot Bot commented Sep 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 756b1b3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@solidjs/signals Patch
test-integration Patch
@solidjs/web Patch
@solidjs/babel-plugin Patch
@solidjs/compiler Patch
@solidjs/diagnostics Patch
@solidjs/element Patch
@solidjs/h Patch
@solidjs/html Patch
solid-js Patch
@solidjs/universal Patch

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

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 35385554074

Coverage remained the same at 71.366%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1035
Covered Lines: 783
Line Coverage: 75.65%
Relevant Branches: 802
Covered Branches: 528
Branch Coverage: 65.84%
Branches in Coverage %: Yes
Coverage Strength: 15.53 hits per line

💛 - Coveralls

@codspeed

codspeed Bot commented Sep 18, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 69.47%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
✅ 171 untouched benchmarks
⏩ 3 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
omit 50.8 µs 30 µs +69.47%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fix/omit-fallback-read-through (756b1b3) with next (ead76f4)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants