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

Deprecate {@debug }...? #14112

Open
Ocean-OS opened this issue Nov 2, 2024 · 7 comments
Open

Deprecate {@debug }...? #14112

Ocean-OS opened this issue Nov 2, 2024 · 7 comments

Comments

@Ocean-OS
Copy link
Contributor

Ocean-OS commented Nov 2, 2024

Describe the problem

Svelte 5 introduced the $inspect rune, which has very similar functionality to the debug tag. This makes me question the necessity of the {@debug } tag.

Describe the proposed solution

I feel like the debug tag probably isn't needed, but the only thing that {@debug } has that $inspect doesn't is the ability to log on every state change. I think the best way to replace this would be to just make calling $inspect without any arguments have the same behavior.
The only issue I see with doing this is that Svelte 5 has already released and this could upset some people.

Importance

nice to have

@Leonidaz
Copy link

Leonidaz commented Nov 2, 2024

$inspect doesn't cause a debugger statement to be inserted which is still useful. Also, the print out form each is different console.log vs @debug vs $inspect.

$inspect is also reactive and will fire multiple times if data changes, so it's nice for tracking reactivity, where as @debug seems to be "static".

they're just different, maybe they can be combined into one with options (which would probably be ugly), or reside on one instance e.g. $dev.inspect, $dev.debug.

@Ocean-OS
Copy link
Contributor Author

Ocean-OS commented Nov 2, 2024

$inspect doesn't cause a debugger statement to be inserted which is still useful. Also, the print out form each is different console.log vs @debug vs $inspect.

You can use $inspect(...).with to make it call a debugger statement. If you want the logs to be exactly the same, you could do something like this:

$inspect({data}).with((type,...parts)=>{
    console.log(...parts);
    debugger; //if you want
})

$inspect is also reactive and will fire multiple times if data changes, so it's nice for tracking reactivity, where as @debug seems to be "static".

I don't quite understand what you mean by this, @debug fires when its data changes, just like $inspect.

they're just different, maybe they can be combined into one with options (which would probably be ugly), or reside on one instance e.g. $dev.inspect, $dev.debug.

Perhaps, or maybe it could be a part of $inspect, like $inspect(...).debug.

@Leonidaz
Copy link

Leonidaz commented Nov 2, 2024

$inspect doesn't cause a debugger statement to be inserted which is still useful. Also, the print out form each is different console.log vs @debug vs $inspect.

You can use $inspect(...).with to make it call a debugger statement. If you want the logs to be exactly the same, you could do something like this:

$inspect({data}).with((type,...parts)=>{
    console.log(...parts);
    debugger; //if you want
})

Good point but the ergonomics of this as far as the debugger; statement is pretty hairy, it's just hard to beat the simplicity of @debug. In general, I agree with you, it'd be great to have "one"-ish way to logging / debugging. Same with stores and signals 😄

$inspect is also reactive and will fire multiple times if data changes, so it's nice for tracking reactivity, where as @debug seems to be "static".

I don't quite understand what you mean by this, @debug fires when its data changes, just like $inspect.

Oh, never saw this since I've always had dev tools open and it would just pause. But, yeah, without debug open, it's reactive, although the effect implementation is different. Good point.

they're just different, maybe they can be combined into one with options (which would probably be ugly), or reside on one instance e.g. $dev.inspect, $dev.debug.

Perhaps, or maybe it could be a part of $inspect, like $inspect(...).debug.

Maybe, just a rune called $debug that would work the same as as $inspect but would break execution with a debugger; statement. And, allow $debug() to have no parameters for a quick break point.

The other differences, from what I recall seeing in the issues is @debug is not deeply reactive (haven't tested yet). Deeply reactive is probably preferable.

@debug is async vs $inspect seems to be sync as I recall the team mentioning it, and will fire first on change. For async we can use $effect() but it's not allowed in the template. Maybe, via options params for $inspect...

TBH, while ultimately something will need to give, I think that having both stores and signals around is a much bigger confusion.

@Ocean-OS
Copy link
Contributor Author

Ocean-OS commented Nov 2, 2024

Maybe, just a rune called $debug that would work the same as as $inspect but would break execution with a debugger; statement. And, allow $debug() to have no parameters for a quick break point.

To be honest, I think too many runes would lead to confusion and unnecessary complexity. This is why there's $state.raw instead of something like $immutable, for example.

The other differences, from what I recall seeing in the issues is @debug is not deeply reactive (haven't tested yet). Deeply reactive is probably preferable.

After testing, I have found it to be deeply reactive, just like $inspect.

@debug is async vs $inspect seems to be sync as I recall the team mentioning it, and will fire first on change. For async we can use $effect() but it's not allowed in the template. Maybe, via options params for $inspect...

$inspect uses $effect under the hood, and runs asynchronously using microtasks.

@Leonidaz
Copy link

Leonidaz commented Nov 2, 2024

Maybe, just a rune called $debug that would work the same as as $inspect but would break execution with a debugger; statement. And, allow $debug() to have no parameters for a quick break point.

To be honest, I think too many runes would lead to confusion and unnecessary complexity. This is why there's $state.raw instead of something like $immutable, for example.

Yeah, true, it would be in line with what has been done. It's just .with is kind of in the way if $inspect.debug was the name but maybe it's not a biggie. I find the ergonomics though not attractive. Although, maybe if it's called $inspect.break it would kind of make more sense. Once we figure out the sync vs async of $inspect (read your comment but still unclear) and if async is needed for logging then would need to figure out how to codify that within the same rune.

I also like $dev.inspect and $dev.break or something like that as it would also indicate that these runes are only available in dev mode and are removed in the prod builds.

The other differences, from what I recall seeing in the issues is @debug is not deeply reactive (haven't tested yet). Deeply reactive is probably preferable.

After testing, I have found it to be deeply reactive, just like $inspect.

Interesting... maybe something has changed. Currently, just for posterity, there seems to be a compilation limitation for @debug to track nested props, like in this modified example in the html comments above @debug: can't debug nested object prop (commented out)

@debug is async vs $inspect seems to be sync as I recall the team mentioning it, and will fire first on change. For async we can use $effect() but it's not allowed in the template. Maybe, via options params for $inspect...

$inspect uses $effect under the hood, and runs asynchronously using microtasks.

Yeah, effects run in microtasks but there is definitely some difference, as $inspect runs before @debug even if it's specified after @debug. You can see this behavior in the console in the example that I provided above. I didn't look any deeper into the code to fully decipher it but it seems that the internal inspect_effect is calling create_effect with a sync param set to true. inspect_effect()

in the playground example that I mentioned above, $inspect gets compiled to:

	const stringified_text_1 = $.derived(() => $.inspect(() => [user.person.something.much.deeper], (type, ...rest) => {
		console.log(...$.log_if_contains_state("log", type, ...rest));
	}) ?? "");

vs @debug

	$.template_effect(() => {
		console.log({ user: $.snapshot(user) });
		debugger;
	});

@Ocean-OS
Copy link
Contributor Author

Ocean-OS commented Nov 4, 2024

I also like $dev.inspect and $dev.break or something like that as it would also indicate that these runes are only available in dev mode and are removed in the prod builds.

This would be nice, but also problematic since Svelte 5 has already released; it wouldn't be very beneficial to introduce a breaking change two weeks after releasing a new version. Not to mention that $inspect has already become the accepted way to log state changes, and it wouldn't make sense to dramatically change its syntax in the next version, just to add a new feature to it.

Currently, just for posterity, there seems to be a compilation limitation for @debug to track nested props, like in this modified example in the html comments above @debug: can't debug nested object prop (commented out)

To be honest, this seems like a limitation of @debug and another reason to deprecate it.

Yeah, effects run in microtasks but there is definitely some difference, as $inspect runs before @debug even if it's specified after @debug. You can see this behavior in the console in the example that I provided above. I didn't look any deeper into the code to fully decipher it but it seems that the internal inspect_effect is calling create_effect with a sync param set to true. inspect_effect()

I see what you mean, $inspect is in fact synchronous.

@Leonidaz
Copy link

Leonidaz commented Nov 4, 2024

I also like $dev.inspect and $dev.break or something like that as it would also indicate that these runes are only available in dev mode and are removed in the prod builds.

This would be nice, but also problematic since Svelte 5 has already released; it wouldn't be very beneficial to introduce a breaking change two weeks after releasing a new version. Not to mention that $inspect has already become the accepted way to log state changes, and it wouldn't make sense to dramatically change its syntax in the next version, just to add a new feature to it.

yeah, agreed. I thought maybe it's easier to introduce something new without changing what's been released and then deprecate. but, at this point, one way of doing things, whatever that ends up being would be great.

Currently, just for posterity, there seems to be a compilation limitation for @debug to track nested props, like in this modified example in the html comments above @debug: can't debug nested object prop (commented out)

To be honest, this seems like a limitation of @debug and another reason to deprecate it.

Yep, thought I'd point out all of the differences to hopefully help clarify the current behavior and make a good decision.

Yeah, effects run in microtasks but there is definitely some difference, as $inspect runs before @debug even if it's specified after @debug. You can see this behavior in the console in the example that I provided above. I didn't look any deeper into the code to fully decipher it but it seems that the internal inspect_effect is calling create_effect with a sync param set to true. inspect_effect()

I see what you mean, $inspect is in fact synchronous.

Looks like it. I took your example and just replaced Date.now() with the performance timers as the former is not precise.
So, yeah, looks like it's sync, although diffs are not 0 but even running sync through the initial code takes some time

performance timers

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

No branches or pull requests

3 participants