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

[@vue/reactivity] Map and Set lookups behave differently after being proxied #799

Closed
nmsmith opened this issue Mar 5, 2020 · 1 comment
Labels
🐞 bug Something isn't working

Comments

@nmsmith
Copy link

nmsmith commented Mar 5, 2020

Version

3.0.0-alpha.7

Reproduction link

https://jsfiddle.net/k571vhbu/1/

Steps to reproduce

Insert some reactive() values into a non-reactive Set or Map. Wrap the Set or Map in reactive(). The inserted values will no longer match as keys, making get(), has(), and delete() return undefined & false.

What is expected?

After being wrapped in a reactive() proxy, the observable behaviour of a Set or Map remains unchanged.

What is actually happening?

Wrapped Sets and Maps behave differently, as described.


This behavioural bug is a result of the proxy code in @vue/reactivity unwrapping proxied keys before passing them to the underlying Map and Set methods, even if the keys already present are proxied (because they were inserted into the raw Map/Set).

@LinusBorg
Copy link
Member

Related code:

https://github.com/vuejs/vue-next/blob/fb4856b36375fcf3eecaf89f260b272052a0b432/packages/reactivity/src/collectionHandlers.ts#L75-L87

The cause of this bug is that we assume that the raw Map / Set contains no proxies, and instead only contains raww values.

So we probably have to check for both the original raw value as well as the reactive proxy, and likely do this in more places than the function linked above.

One caveat that this would have to cover / work around it that we could have both the original and proxy object in the Set/Map:

const value =  x: 0}
const wrappedValue = VueReactivity.reactive({value);

const set = new Set();
set.add(value)
set.add(wrappedValue) // should this warn that the original is already in the set or something?

const wrappedSet = VueReactivity.reactive(set);

wrappedSet.delete(wrappedValue) // which of the two should this delete? 

@LinusBorg LinusBorg added the 🐞 bug Something isn't working label Mar 5, 2020
yyx990803 added a commit that referenced this issue Mar 6, 2020
@github-actions github-actions bot locked and limited conversation to collaborators Nov 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
🐞 bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants