Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reassigning an object to a writable store using $-prefix causes its value to become a proxy in runes mode #15281

Open
tomoam opened this issue Feb 13, 2025 · 3 comments · May be fixed by #15283

Comments

@tomoam
Copy link
Contributor

tomoam commented Feb 13, 2025

Describe the bug

related #15280

When writing a Svelte component like the following in runes mode...

<script>
	import { writable } from 'svelte/store';

	let obj = writable({ name: 'foo'});

	const clone1 = structuredClone($obj); // OK
	
	$obj = { name: 'bar' };

	const clone2 = structuredClone($obj); // error
</script>

{ name: 'bar' } becomes proxied in the JS output as shown below:

	let obj = writable({ name: 'foo' });
	const clone1 = structuredClone($obj());

	$.store_set(obj, $.proxy({ name: 'bar' })); // here

	const clone2 = structuredClone($obj());

In the following cases, this issue does not occur:

  • When assigning a primitive value instead of an object
  • When using the writable store’s set method instead of the = operator
  • In non-runes mode

Reproduction

https://svelte.dev/playground/77f58c2f61394b4ca4efc5b62ea63d29?version=5.20.0

Logs

System Info

System:
    OS: macOS 14.6.1
    CPU: (12) arm64 Apple M2 Pro
    Memory: 1.45 GB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.18.0 - ~/.nvm/versions/node/v20.18.0/bin/node
    npm: 10.8.2 - ~/.nvm/versions/node/v20.18.0/bin/npm
    pnpm: 9.7.0 - /opt/homebrew/bin/pnpm
  Browsers:
    Chrome: 133.0.6943.54
    Safari: 17.6
    Safari Technology Preview: 18.2

Severity

annoyance

@ginpei
Copy link

ginpei commented Feb 14, 2025

Is it possible for store to return proxy always?

From us, user sight, store looks to return original object or proxy unpredictably. If it was proxy always, we could avoid "lucky shot" and deal with improper usage from the beginning. How about doing so in dev mode at least?

@tomoam
Copy link
Contributor Author

tomoam commented Feb 14, 2025

I also tested the behavior in Svelte 4 and observed that when changing a store’s value, it was not proxified.

Below are the demo code and a table of the results:

Svelte Version Mode How to write Proxified
4 - store.set(object) false
4 - store.update(v => v = object) false
4 - $store = object false
5 Non-runes store.set(object) false
5 Non-runes store.update(v => v = object) false
5 Non-runes $store = object false
5 Runes store.set(object) false
5 Runes store.update(v => v = object) false
5 Runes $store = object true

Considering backwards compatibility with Svelte 4, I believe that having the store’s value proxified when reassigning to the store with $-prefix is unintentional. A store’s value should consistently not be proxified.

@ginpei
Copy link

ginpei commented Feb 14, 2025

A store’s value should consistently not be proxified

This sounds good to me. It'd be great if the result was either always original or always proxy

Anyway I'm going to replace $store = object with store.get(object) on our migrated code for now. Thanks for hard working, Svelte team!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants