Skip to content

fix: bindable props on class instances (spread + mount)#18143

Open
ashishkr96 wants to merge 1 commit intosveltejs:mainfrom
ashishkr96:fix/class-instance-props-bindable
Open

fix: bindable props on class instances (spread + mount)#18143
ashishkr96 wants to merge 1 commit intosveltejs:mainfrom
ashishkr96:fix/class-instance-props-bindable

Conversation

@ashishkr96
Copy link
Copy Markdown

Summary

Closes #18140.

Object.getOwnPropertyDescriptor only inspects own properties, so when a class instance was passed as props (<Comp {...instance} /> or mount(Comp, instance)), Svelte couldn't find the inherited accessor and silently dropped the setter. Reads worked, writes didn't — bindings became no-ops, which made it awkward to use classes in component tests where mount/render is the natural entry point.

This walks the prototype chain (stopping at Object.prototype) when resolving property descriptors in:

  • spread_props_handler.set and getOwnPropertyDescriptor (client) — so <Comp {...instance} /> finds the prototype accessor.
  • prop() (client, the mount path) — same, plus the setter is now invoked via props[key] = v so this resolves to the class instance and re-enters the spread proxy's set trap when relevant.
  • spread_props and bind_props (server) — SSR previously relied on Object.keys/getOwnPropertyDescriptor, which also missed inherited accessors. Inherited accessors are now copied with get/set bound to the source object so this survives.

A shared get_descriptor_in_chain helper lives in internal/shared/utils.js.

Test plan

  • bind-and-spread-class-instance<Comp {...accessor} /> and <Comp {...field} /> (class fields with $state) round-trip writes through to the parent's class instance, on dom/hydrate/ssr/async-ssr.
  • mount-class-instance-props — same coverage via mount(Component, classInstance).
  • Full runtime-runes, runtime-legacy, server-side-rendering, hydration suites still green.
  • pnpm check and pnpm lint pass.

`Object.getOwnPropertyDescriptor` skips inherited accessors, so spread/`mount`
props that come from class instances (including class fields with `$state`)
silently lost their setter and bindings became no-ops.

Walks the prototype chain to find accessor descriptors, routes spread-proxy
writes through `props[key] = v` so `this` resolves correctly, and applies the
same fix to SSR `spread_props` / `bind_props`.

Closes sveltejs#18140

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 26, 2026

🦋 Changeset detected

Latest commit: 2d2bae5

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

This PR includes changesets to release 1 package
Name Type
svelte 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

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.

Passing a class isntance as props to mount doesnt propagate writes

1 participant