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

Snippet exports cause errors in VSCode #2640

Closed
HanielU opened this issue Dec 28, 2024 · 3 comments
Closed

Snippet exports cause errors in VSCode #2640

HanielU opened this issue Dec 28, 2024 · 3 comments
Labels
bug Something isn't working Fixed Fixed in master branch. Pending production release.

Comments

@HanielU
Copy link

HanielU commented Dec 28, 2024

Describe the bug

In VSCode the svelte language server breaks when exporting a snippet that:

  • makes use of a Svelte component that spreads the props gotten as an argument
  • uses an #if statement referencing an "unknown" identifier like Error (i.e it can't find it in the file scope)

Reproduction

<!-- App.svelte -->
<script lang="ts" module>
  import Dummy from "./DummyComponent.svelte";
  import type { HTMLAttributes } from "svelte/elements";
  
  export { errorBoundary }; // ERROR HERE: cannot find name 'errorBoundary'
  export { WithProps }; // ERROR HERE: cannot find name 'WithProps'
</script>

{#snippet errorBoundary(error: unknown, reset: () => void)}
  <Dummy class="text-red">This is a boundary</Dummy>
  
  {#if error instanceof Error}
    <p>This is causing the error in the module script</p>
  {/if}
  
  <button onclick={reset}>Reset</button>
{/snippet}

{#snippet WithProps(props: HTMLAttributes<HTMLDivElement>)}
  <Dummy {...props}>
    <h1>This is a snippet with Props</h1>
  </Dummy>
{/snippet}
<!-- DummyComponent.svelte -->
<script lang="ts">
  let {children, ...rest} = $props()
</script>

<div {...rest}>
  {@render children()}
</div>

Expected behaviour

There shouldn't be an error because the compiler doesn't break as shown in this REPL

System Info

  • OS: Windows 11 Pro
  • IDE: VSCode v1.93.1

Which package is the issue about?

Svelte for VS Code extension, svelte-language-server

Additional Information, eg. Screenshots

image

@HanielU HanielU added the bug Something isn't working label Dec 28, 2024
@Wombosvideo
Copy link

Wombosvideo commented Jan 4, 2025

Additions to the bug description

More generally it seems to happen when trying to export snippets that reference any declaration defined outside1 that is not a parameter of the snippet.
This makes sense for declarations defined in the component's instance2. This should not happen for snippets that do not reference such declarations but reference declarations from the <script module>. And it certainly should not happen for snippets with @const declarations referencing parameters only.

Reproduction

I've ran into this issue when trying to create formatter snippets. It seems to happen

  • when using a @const declaration. Does not impact compilation.
  • when using a parameter with a non-basic3 type. Does not impact compilation.
<script lang="ts" module>
  export { noConst }; // Works just fine
  export { withConst }; // ts(2304): Cannot find name 'withConst'.
  export { withNonPrimitiveParam }; // ts(2304): Cannot find name 'withNonPrimitiveParam'.
</script>

{#snippet noConst(foo: string)}
  {foo}
{/snippet}

{#snippet withConst(foo: string)}
  {@const bar = foo}
  {bar}
{/snippet}

{#snippet withNonPrimitiveParam(foo: Record<string, string>)}
  Not even using the param.
{/snippet}

Reproduction (old)

I've ran into this issue when trying to create formatter snippets, with one formatter converting from svx3 resulting in the mentioned Cannot find name 'withDependencies' TypeScript error. The error does not impact compilation and everything works as expected.

<script lang="ts" module>
  import { compile } from 'mdsvex';

  // Fix for mdsvex: (https://stackoverflow.com/a/73396215)
  if (typeof globalThis.window !== 'undefined') {
    window.process = {
      cwd: () => '/'
    } as NodeJS.Process;
  }

  export { noDependencies }; // Works just fine
  export { withDependencies }; // ts(2304): Cannot find name 'withDependencies'.
</script>

{#snippet noDependencies(content: string)}
  {content}
{/snippet}

{#snippet withDependencies(content: string)}
  {#await compile(content) then compiled}
    {@html compiled?.code}
  {/await}
{/snippet}

Expected behaviour

  • The error only occurs if a non-module1 declaration is used.
  • The error is more descriptive. Example: Cannot export snippets referencing variables defined outside the <script module>

Notes

I've faces this issue when using the paraglide-svelte package and adding an anchor <a> without data-no-translate to the snippet I was trying to export. Breaks compilation. (see related issue)

Footnotes

  1. a declaration that is not defined in the <script module>, i.e. a declaration that is neither a snippet parameter nor a @const declaration within the snippet's body. 2

  2. i.e. imports or variables in the <script> tag, or other top-level snippets depending on non-module declarations

  3. i.e. none of any | boolean | never | null | number | object | string | undefined | unknown | void | {} or an array or tuple containing these types. 2

@Wombosvideo
Copy link

Wombosvideo commented Jan 5, 2025

After further experimenting, I can confirm it also does break compilation (vite-plugin-svelte) when using paraglide-svelte and trying to export a snippet with an anchor tag that does not have the data-no-translate attribute set.

dummdidumm added a commit that referenced this issue Jan 8, 2025
Instead of collecting the types/values that are allowed, we collect the types/values that are _disallowed_ - this makes it possible to reference global values/types and still have them properly be declared as hoistable

#2640
@dummdidumm dummdidumm added the Fixed Fixed in master branch. Pending production release. label Jan 8, 2025
dummdidumm added a commit that referenced this issue Jan 8, 2025
Instead of collecting the types/values that are allowed, we collect the types/values that are _disallowed_ - this makes it possible to reference global values/types and still have them properly be declared as hoistable

#2640
dummdidumm added a commit that referenced this issue Jan 8, 2025
Instead of collecting the types/values that are allowed, we collect the types/values that are _disallowed_ - this makes it possible to reference global values/types and still have them properly be declared as hoistable

#2640
@zeyus
Copy link

zeyus commented Jan 8, 2025

I just noticed this error, and it is now fixed (thanks @dummdidumm !!), except, it reappears if you set <svelte:options runes={true} />

Screenshot 2025-01-08 at 14 53 13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Fixed Fixed in master branch. Pending production release.
Projects
None yet
Development

No branches or pull requests

4 participants