Skip to content

fix: generateAcornTypeScript breaks when two acorn copies exist #41

@fubits1

Description

@fubits1

Context

When upgrading @sveltejs/vite-plugin-svelte to 7.0.0 and vite from v7 to vite@8.0.0-beta.15 in an existing SvelteKit project with Bun as package manager, starting the dev server started to throw.

Problem

It seems that under certain conditions, multiple versions of acorn can exist in the repository. Using Claude Code I managed to narrow it down:

In my project bun pm why acorn printed:

Consumer Version
espree@11.1.1 (ESLint 10) acorn@^8.16.0
espree@10.4.0 (svelte-eslint-parser) acorn@^8.15.0
@sveltejs/kit acorn@^8.14.1
svelte acorn@^8.12.1

Somehow at some point, Bun hoisted 8.15.0 into the top-level.

So @sveltejs/acorn-typescript used node_modules/acorn(8.15.0) but the Svelte compiler probably went for node_modules/svelte/node_modules/acorn.

However, the exact versions don't matter. Two copies of the same version from different paths would also break. It seems that the actual problem is:

src/tokenType.ts imports tokTypes and keywordTypes at module level (lines 2, 15). These are singleton objects, I assume.

The helper functions inside generateAcornTypeScript() close over these module-level singletons instead of using the _acorn parameter.

Meanwhile tsPlugin() in src/index.ts (line 168) correctly uses Parser.acorn || acornNamespace and derives tt = _acorn.tokTypes.

When the plugin is applied via Parser.extend() to a Parser from a different acorn instance, all internal token === tokTypes.name comparisons fail because the object references differ.

TypeScript parsing silently falls through to plain JS, causing js_parse_error on any <script lang="ts">.

Suggested fix

Inside generateAcornTypeScript(), acorn is already derived from _acorn.Parser.acorn || _acorn (line 17).

Use acorn.tokTypes and Object.values(acorn.keywordTypes) instead of the module-level imports.

I drafted a PR.

Related

The js_parse_error in a Bun project is also mentioned in #36 - maybe the actual problem there is the same as here.

Workaround

Either use pnpm or force a single acorn copy via package.json override:

{
  "overrides": {
    "acorn": "8.16.0"
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions