Skip to content

fix(dev): clear the resolver cache when a file is created or deleted - #10986

Merged
h-a-n-a merged 2 commits into
rolldown:mainfrom
waltuov:fix/dev-resolver-cache-create-delete
Sep 29, 2026
Merged

h-a-n-a merged 2 commits into
rolldown:mainfrom
waltuov:fix/dev-resolver-cache-create-delete

Conversation

@waltuov

@waltuov waltuov commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Fixes #10487

The resolver caches misses as well as hits, and the dev engine only cleared it on a full build or a tsconfig change. So deleting a still imported file gave a silent Noop, and a missing file kept failing to resolve after it came back.

Now an incremental dev task clears the resolver cache when its batch has a create or delete, when a watched package.json changed, or when the previous task failed. The last case is for recovery. The failed round cached the miss, and the file can come back without a create event. For example, a file that was never imported is not watched, so after creating it the next importer edit would hit the cached miss again. Build watch mode documents the same recovery in internal-docs/watch-mode/implementation.md. The Rust fixture harness also reports a recreated file as an update.

Tests: the acceptance test in dev-watch.test.ts is no longer skipped. It fails before this change and passes after. delete_file_used step 0 is now an unresolved import error, as the issue expected, and its README is updated. internal-docs/dev-engine/implementation.md has a new §9c.

Alternatives: clearing on every task, like build watch mode, is simpler but throws the cache away on every edit. Per path invalidation needs a new oxc_resolver API.

Worth a look: the clear after a failed task, and editors that save by rename, since each such save now clears the cache.

@codspeed

codspeed Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 7 untouched benchmarks
⏩ 10 skipped benchmarks1


Comparing waltuov:fix/dev-resolver-cache-create-delete (56938e7) with main (3f76b5c)

Open in CodSpeed

Footnotes

  1. 10 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

The resolver caches misses as well as hits, and the dev engine only
cleared it on a full build or a tsconfig change. Deleting a still
imported file ended in a silent Noop, and a missing file kept failing
to resolve after it came back.

An incremental dev task now clears the resolver cache when its batch has
a create or delete, when a watched package.json changed, or when the
previous task failed.

Fixes rolldown#10487
@waltuov
waltuov force-pushed the fix/dev-resolver-cache-create-delete branch from 9e88261 to c94154a Compare September 25, 2026 10:49
@h-a-n-a h-a-n-a self-assigned this Sep 29, 2026
# Conflicts:
#	internal-docs/dev-engine/implementation.md
h-a-n-a
h-a-n-a approved these changes Sep 29, 2026 •
@h-a-n-a
h-a-n-a enabled auto-merge (squash) September 29, 2026 08:14
@h-a-n-a
h-a-n-a merged commit 8546e7a into rolldown:main Sep 29, 2026
31 checks passed
@waltuov
waltuov deleted the fix/dev-resolver-cache-create-delete branch September 29, 2026 08:40
Brooooooklyn added a commit that referenced this pull request Sep 30, 2026
Conflicted files:
- Cargo.lock: took main's lock, let cargo re-add our entries (arc-swap,
  async-broadcast, async-lock, async-task, napi-async-runtime 0.2.3,
  parking_lot_core git patch ac046ba4; async-scoped / pin-project dropped),
  then re-applied our event-listener 5.4.2 pin (RUSTSEC-2026-0221).
- pnpm-workspace.yaml: kept main's oxc 0.152.0 pins and the removed
  vitepress>vite override; kept our emnapi override and catalog entries
  (@napi-rs/cli ^3.10.5, async-runtime, buffer, miniflare, wrangler).
- pnpm-lock.yaml: took main's lock and ran pnpm install; only our
  packages and catalog entries were added.
- crates/rolldown_fs_watcher/src/{lib.rs,watcher.rs}: kept main's
  FsWatcher (owns the watched paths, watch_paths/is_watched, event
  translation in notify/). Replaced our PathsSource trait with a seam on
  the new shape: FsWatcher::with_backend plus public WatcherBackend /
  PathsMut, try_watch_paths (a refused add is an error, still commits,
  aggregates add+commit errors) and is_registered (exact membership).
- crates/rolldown_watcher/src/task_fs_event_handler.rs: GroupFsEventHandler
  (ours) now forwards main's FsEvent batches.
- crates/rolldown_watcher/src/watch_task.rs: kept per-group shared watcher
  and per-task watched_files; the group registered-path set is now the
  shared FsWatcher's own set (group_registered_files removed); build watch
  registers through try_watch_paths so add failures still drive the
  backoff retry. TaskFsWatcher alias removed.
- crates/rolldown_dev/src/{bundle_coordinator.rs,watcher_event_handler.rs,
  types/coordinator_msg.rs,dev_engine.rs}: dev takes main's FsWatcher-owned
  path set and Vec<FsEvent> messages; kept our watch-registration error
  observers, the extra-path union and unbounded_send; kept both dev_engine
  tests.
- crates/rolldown_dev/src/bundling_task.rs: kept main's resolver cache
  clear (#10986) on our DevCallbackResult-returning run().
- crates/rolldown_binding/src/types/binding_magic_string.rs: kept our
  fallible accessors, renamed to oxc_sourcemap 9's ignore_list.
- internal-docs/{watch-mode,dev-engine}/implementation.md: merged both
  sides; describe the group watcher on top of FsWatcher's path set.
- packages/rolldown/build.ts: kept our WASI/workerd loader bundling and
  workerdPackageApi define, took main's buildRuntimeEntry /
  generateRuntimeTypes and always-inlined __RUNTIME_STRING__, kept our
  WebContainer fallback that adopts the loader's __napiBindingTarget.
- packages/rolldown/tests/dev/dev-lazy-compile.test.ts: took main's
  removal of the tests for the reverted lazy one-request fetch (#10982);
  our skipIf(isSingleThread) guards on the remaining tests stay.
- packages/rolldown/src/rolldown-binding.wasi.cjs: generated; seeded from
  our side (main's metadata lacks the async-runtime host exports and the
  native re-emit refuses it), then regenerated.

Semantic adaptation:
- Test fakes in rolldown_watcher / rolldown_dev implement WatcherBackend
  and are built with FsWatcher::with_backend; assertions on the group set
  query the shared watcher.
- __internalForcePanic (#10989) removed from binding-workerd-proxy.ts and
  from the regenerated wasip1 loaders.

Regeneration order: just build-rolldown, pnpm build-binding:wasi,
pnpm build-binding:wasi-single, just build-rolldown.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T34fMrYCf2V13Mg8BKmnda
Brooooooklyn added a commit that referenced this pull request Sep 30, 2026
…ad flavor

Main #10986 added "deleting an imported file surfaces a resolve error and
recreating it recovers" without the skipIf(isSingleThread) guard the other
dev() cases in this file carry. This PR gates dev() on the CurrentThread
flavor, so the Native Async Runtime job (ROLLDOWN_RUNTIME=single) failed
with ERR_ROLLDOWN_UNSUPPORTED_RUNTIME_FEATURE. Same guard, same reason.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T34fMrYCf2V13Mg8BKmnda
@rolldown-guard rolldown-guard Bot mentioned this pull request Sep 30, 2026
shulaoda added a commit that referenced this pull request Sep 30, 2026
## [1.2.12] - 2026-09-30

### 🚀 Features

- inline common chunks containing import() and deduplicate shared code in lazy chunks (#11034) by @hyfdev
- experimental `inlineCommonChunks` support (#10899) by @hyfdev
- dev: ship imported bindings for HMR partial accept (#10856) by @h-a-n-a

### 🐛 Bug Fixes

- chunking: re-derive chunk exec orders after the runtime leaves its host chunk (#11005) by @hyfdev
- code-splitting: gate member-read init paths on the reading statement (#11039) by @hyfdev
- code-splitting: retain initialization paths through re-exported namespaces (#11037) by @hyfdev
- dev: reject non-ESM output formats in dev mode (#11038) by @h-a-n-a
- dev: align `import.meta.hot.accept` deps with Vite (#10997) by @h-a-n-a
- dev: clear the resolver cache when a file is created or deleted (#10986) by @waltuov
- error: name the resolved specifier in unresolved import diagnostics (#11014) by @linyiru
- make entries-aware chunk merging deterministic (#11002) by @hyfdev
- watch: avoid restarting macOS watcher for unchanged paths (#10992) by @sep2

### 🚜 Refactor

- dev: ship the dev runtime entry as one file (#10998) by @h-a-n-a
- binding: remove `__internalForcePanic` (#10989) by @IWANABETHATGUY

### 📚 Documentation

- fix cloudflare preview builds (#10996) by @sapphi-red
- fix build config loader warning (#10994) by @sapphi-red
- deps: use Vite 8 (#10993) by @sapphi-red

### ⚡ Performance

- dev: only ship rows with dynamic edges in registerGraph (#11019) by @h-a-n-a

### 🧪 Testing

- code-splitting: cover more re-exported namespace shapes (#11042) by @hyfdev
- webcontainer: cover the WebContainer download fallback in plain Node (#10966) by @shulaoda
- dev: pin the runtime entry file layout that Vite serves (#10983) by @h-a-n-a

### ⚙️ Miscellaneous Tasks

- pin VOID_API_URL for the docs deploy (#11041) by @shulaoda
- opt into the WebContainer smoke test for napi bumps and loader changes (#10967) by @shulaoda
- deps: upgrade oxc to 0.152.0 (#11018) by @camc314
- deps: update rust crates (#11012) by @renovate[bot]
- deps: update npm packages (#11011) by @renovate[bot]
- deps: update crate-ci/typos action to v1.50.3 (#11023) by @renovate[bot]
- deps: update test262 submodule for tests (#11022) by @rolldown-guard[bot]
- deps: update rollup submodule for tests to v4.63.5 (#11021) by @rolldown-guard[bot]
- deps: update dependency vite-plus to v1 (#11017) by @renovate[bot]
- deps: update github actions (#11010) by @renovate[bot]
- remove `CLAUDE.md` (#10925) by @iiio2
- verify release debug info by matching file IDs (#10988) by @IWANABETHATGUY
- deps: update rollup submodule for tests to v4.63.4 (#10940) by @rolldown-guard[bot]

### ❤️ New Contributors

* @waltuov made their first contribution in [#10986](#10986)
* @linyiru made their first contribution in [#11014](#11014)
* @sep2 made their first contribution in [#10992](#10992)

Co-authored-by: shulaoda <165626830+shulaoda@users.noreply.github.com>
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

Successfully merging this pull request may close these issues.

[Bug]: deleting a still-imported file yields a silent Noop (resolver cache never invalidated on watch events)

2 participants