Skip to content

An import of a workspace package resolves onto a non-exported local variable of the same name (157 edges in vitejs/vite) #1719

Description

@bompus

On vitejs/vite @ 8492422, indexed at b9ca4b7, 157 cross-file imports edge rows resolve onto a single non-exported local variable.

Every import { defineConfig } from 'vite' across the playground and create-vite templates lands on:

playground/ssr-html/test-stacktrace.js::vite

which is this, at module scope in a file that exports nothing at all:

import { createServer } from 'vite'
// ...
const vite = await createServer({ /* ... */ })

The correct target is the workspace member packages/vite ("name": "vite", exports["."] = "./dist/node/index.js"), which is in the graph.

Counts

rows
edges targeting a node named vite 317
contains (a file holding its own vite node; not at issue) 159
imports, same-file 1
imports, cross-file 157
distinct targets among those 157 1
source files importing from 'vite' 148 / 148

Why the existing guards do not catch it

matchByExactName filters candidates to non-import nodes that are lexically reachable, and commits when exactly one survives. Here one does — the module-level const — so the reference resolves with resolvedBy: 'exact-match' and confidence 0.9.

The bare-import guards do not apply, and correctly so. packages/vite/package.json declares the name vite and pnpm-workspace.yaml globs packages/*, so resolveWorkspaceImport('vite', …) reports the specifier project-local and isBoundToBareImport returns false. The specifier really is project-local; the failure is that the name then matches any node called vite rather than the member's entry.

Measured, on this corpus against the same merge base:

Two places a fix could go, and I do not have a view on which

  1. Export visibility. A module-level binding that the file does not export is not reachable by an import from another file. isLexicallyReachable admits it today. This looks like the general defect — it is not specific to workspace packages, and any non-exported top-level name is a candidate for any same-named import anywhere.
  2. Workspace package resolution. When a specifier resolves to a workspace member, the target should be that member's entry point rather than a name lookup. entryByName already exists for the ArkTS case.

(1) is the broader fix and would subsume this; (2) is narrower and would leave the same shape wherever a package is not a workspace member.

Reproduction

git clone https://github.com/vitejs/vite && cd vite && git checkout 8492422
codegraph init && codegraph index .

Then query the graph for imports edges whose target node is named vite and whose source file differs from the target's file.

Kernel rebuilt from source per arm; index db copied out before reading. Edge rows counted with multiplicity, keyed by source, target and kind — a distinct count reads lower because one source line can carry two genuine references at different columns.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions