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

void <identifier> statements are removed #4041

Open
rChaoz opened this issue Jan 19, 2025 · 3 comments
Open

void <identifier> statements are removed #4041

rChaoz opened this issue Jan 19, 2025 · 3 comments

Comments

@rChaoz
Copy link

rChaoz commented Jan 19, 2025

Cause

void <identifier> statements are removed, you can test by running await transform("<input>"):

// input:
let a = 123; void a
// output:
let a = 123;

Why does this matter?

In Svelte, runes are used to implement reactivity. For example, let a = $state(123) is transformed into let a = $.state(123), and all accesses of the variable are transformed from a to $.get(a). Most importantly, $.get() inside special sections called effects, will be tracked, causing the effect code to re-run whenever the variable changes. Svelte's transformation happens after esbuild.

Sample transformation:

// input:
let a = $state(0)
$effect(() => {
    void a;
    console.log("effect runs")
})
// esbuild:
let a = $state(0)
$effect(() => {
    console.log("effect runs")
})
// svelte:
import * as $ from "svelte/internal"
let a = $.state(0)
$.user_effect(() => {
    console.log("effect runs")
})

The correct final output should be:

import * as $ from "svelte/internal"
let a = $.state(0)
$.user_effect(() => {
    void $.get(a)
    console.log("effect runs")
})

If esbuild were to run on this code, the void statement won't get removed, as it knows side-effects are possible.

Problem

I couldn't find a combination of options to prevent the void statement from getting removed. Is there an option to stop this from happening? If not, then I think either esbuild shouldn't remove such statements by default, especially when tree-shaking is not enabled, or at least this should be configurable somehow.

@hyrious
Copy link

hyrious commented Jan 19, 2025

It seems you can remove the void and esbuild will preserve the single identifider statement (see it online):

let a = $state(0)
$effect(() => { a; console.log(1) })
let f = () => a++

@threepointone
Copy link

why are you running esbuild before the svelte pass? esbuild can't give guarantees over custom syntax assumptions

@rChaoz
Copy link
Author

rChaoz commented Jan 20, 2025

Because of many reasons: this is the Vite pipeline, which uses esbuild before any other plugin, among other things, to transform Typescript into Javascript.

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

No branches or pull requests

3 participants