sveltejs / svelte-devtools

A browser extension to inspect Svelte application by extending your browser devtools capabilities
https://chromewebstore.google.com/detail/svelte-devtools/kfidecgcdjjfpeckbblhmfkhmlgecoff
MIT License
1.49k stars 79 forks source link

Updating prop values of an object with a function property causes an exception #194

Closed davidjayb closed 7 months ago

davidjayb commented 7 months ago

Describe the bug When trying to update a value in an object with a function property, if the function is called in the page or component it will throw an exception that the function does not exist. Here is an example updating an object in an array:

Uncaught (in promise) TypeError: ctx[1].<function_name> is not a function
    update <component_name>.svelte:25
    p courier.js:264
    update <component_name>.svelte:510
    p courier.js:264
    update scheduler.js:119
    flush scheduler.js:79
    promise callback*schedule_update scheduler.js:20
    make_dirty Component.js:81
    ctx Component.js:139
    $inject_state <component_name>.svelte:612
    __svelte_devtools_inject_state courier.js:369
    <anonymous> - eval code:1

To Reproduce Steps to reproduce the behavior:

  1. Create a component that accepts props that includes a class (or base object) with functions.
  2. Reference the function in the component.
  3. Update a prop value in the dev tools.

Expected behavior The update should succeed and the function should be intact.

Environment

Additional context

This appears to be due, in part, to how objects are cloned for display in the devtools chrome:

https://github.com/sveltejs/svelte-devtools/blob/master/src/client/index.js#L99

Functions need to be turned into a string form. Furthermore, the clone does will not include object functions in serialization if they inherited from a class.

I also noticed this issue if object references such as URL are made in a component:

$: search = $page.url.searchParams.get('search');

Updating the component will produce an error because the url will no longer have a searchParams property.

ignatiusmb commented 7 months ago

Thank you for the report, I think I get the sense of what the problem and solution is. Can you provide a minimal repro though, I couldn't seem to get it consistently or even at all.

davidjayb commented 7 months ago

Here is the test bed: https://github.com/davidjayb/svelte-devtools-194

With the devtools, you can notice the class function returning undefined if you update the prop: https://github.com/davidjayb/svelte-devtools-194/blob/main/src/routes/%2Bpage.svelte#L16 https://github.com/davidjayb/svelte-devtools-194/blob/main/src/routes/%2Bpage.svelte#L24 https://github.com/davidjayb/svelte-devtools-194/blob/main/src/routes/%2Bpage.svelte#L32

Screenshot 2024-04-05 at 9 08 56 AM

To receive the issue with the $page.url.searchParams is a bit trickier to encounter. On the page /search update the prop from the Root component. Screenshot 2024-04-05 at 9 07 52 AM Screenshot 2024-04-05 at 9 08 06 AM

After updating the PR repo to the latest master it seems updating props has broken. However once that is fixed you should be able to test things out.

ignatiusmb commented 7 months ago

Thank you for the detailed repro! I ended up reworking how the inject function is called in #205. There's still some edge cases with classes and getters, which I'll continue working in #195