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

feat: allow $inspect reactivity map, set, date #11164

Merged
merged 5 commits into from
Apr 18, 2024

Conversation

tanhauhau
Copy link
Member

Relates to #11151.

Currently the $inspect runes work based on deep_read the state through properties and getters. This seems to work with ReactiveSet and ReactiveMap because it has a get size() getter.
And it doesn't work with the ReactiveDate because it has neither state properties nor getters.

This PR attempts to fix this by introduce a Symbol('$inspect') method to the reactivity objects. This allow the reactivity objects to implements its own logic to trigger the inspect callbacks.

We could export the Symbol('$inspect') to allow it to work for user defined reactivity object.

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • Prefix your PR title with feat:, fix:, chore:, or docs:.
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests and linting

  • Run the tests with pnpm test and lint the project with pnpm lint

Copy link

changeset-bot bot commented Apr 14, 2024

🦋 Changeset detected

Latest commit: 9d68231

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

@dummdidumm
Copy link
Member

dummdidumm commented Apr 14, 2024

I like the idea! I think we can expand it to autogenerate this symbol field in dev mode onto classes using runes. For example if you write

class Counter {
  count = $state(0)
  double = $derived(this.count * 2)
}

then in dev mode the compiler will autogenerate the symbol for that class and return the count signal from it.
Then we can get rid of the "invoke getters if we come across them" logic we have right now in the inspect function which is prone to invoke unwanted side effects.

I'm not fully sure yet what's the best API for the inspect symbol. Should it invoke the signals? Should it return an array of signals the inspect function can then traverse?

@tanhauhau tanhauhau force-pushed the tanhauhau/fix/inspect-reactive branch from fcdfd35 to 07b32dc Compare April 14, 2024 09:28
@harrisi
Copy link

harrisi commented Apr 14, 2024

Could you go one step further, and instead of making $inspect special, define some other interface that a class could implement that $state interacts with?

I've been thinking about how to redefine the Reactive objects to a has-a, rather than is-a, relationship. One way I thought to do that is to have some known static property of "read" and "write" methods that could be read when doing $state(new ReactiveSet()). Or some known method(s) or something.

Then when you need the raw Set (or whatever), you could call unstate on it, which could call an unstate method.

I think this could also be used to enable $inspect on user defined classes as well.

Copy link
Contributor

@trueadm trueadm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just need to fix the linting issue :)

@trueadm
Copy link
Contributor

trueadm commented Apr 14, 2024

I like the idea! I think we can expand it to autogenerate this symbol field in dev mode onto classes using runes. For example if you write

class Counter {
  count = $state(0)
  double = $derived(this.count * 2)
}

then in dev mode the compiler will autogenerate the symbol for that class and return the count signal from it. Then we can get rid of the "invoke getters if we come across them" logic we have right now in the inspect function which is prone to invoke unwanted side effects.

I'm not fully sure yet what's the best API for the inspect symbol. Should it invoke the signals? Should it return an array of signals the inspect function can then traverse?

I think this can be done in a follow up, as it might widely implications for what we do with ownership too.

Copy link
Member

@dummdidumm dummdidumm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to discuss what the symbol contains exactly and whether or not it makes sense to auto generate that first (see my comment above)

I think this can be done in a follow up, as it might widely implications for what we do with ownership too.

Then let's discuss that first and think about it holistically. We can always incrementally work towards that once we figured out a path, but I'd like to first see if we're going in the right direction

@trueadm
Copy link
Contributor

trueadm commented Apr 14, 2024

@dummdidumm What I mean is that there have been many complaints about $inspect not working with the built in reactivity classes now, so maybe we should just import the prototypes from those modules given it's all DEV? We can look into the idea around using a symbol differently and change this if need be, but the two things are definite. The priority of one is greater than the other.

@tanhauhau tanhauhau force-pushed the tanhauhau/fix/inspect-reactive branch from 5eb625b to d38f89e Compare April 15, 2024 00:56
@dummdidumm dummdidumm dismissed their stale review April 15, 2024 15:10

ok to proceed, we can always change this later, after a bit of discussion we concluded it doesn't affect other stuff directly right now

@trueadm
Copy link
Contributor

trueadm commented Apr 17, 2024

@tanhauhau You have some linting issues.

@tanhauhau
Copy link
Member Author

@tanhauhau You have some linting issues.

@trueadm thanks. i've fixed them

@trueadm trueadm merged commit 43d13e9 into sveltejs:main Apr 18, 2024
6 of 8 checks passed
@Rich-Harris
Copy link
Member

I'm not sure this is the right fix. If I inspect a normal Map, this is what gets logged in Chrome and Firefox:

  • Chrome:
    image

  • Firefox
    image

This is what happens with a reactive Map:

  • Chrome
    image

  • Firefox
    image

This isn't very useful. I'm going to revert this and take another run at it

@trueadm
Copy link
Contributor

trueadm commented Apr 18, 2024

@Rich-Harris This was working fine when I reviewed it, I believe it's likely because of the other PR that ensures we don't duplicate data landed (#11200). I wonder what API is used for introspection of Maps for dev tools

Rich-Harris added a commit that referenced this pull request Apr 18, 2024
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.

5 participants