denoland/celldPublic

self-hosted, distributed Durable Objects

Import scanner misses minified brace imports (`import{x}from"y"`), breaking nodejs_compat builtins like node:events

TH

## What happened

A production Worker bundle (minified by esbuild) fails to instantiate on celld with:

``` WARN celld::js::modules: resolve: no stub for specifier spec=node:events Error: stateless Worker failed to load Caused by: instantiate: <none> ```

`node:events` is implemented (`node_events.js` exists and is registered in `LAZY_MODULES`), but the stub is never registered for this bundle.

## Root cause

`IMPORT_RE` in `crates/celld/js/modules.rs` requires at least one whitespace character between `import` and the clause:

```rust regex::Regex::new(r#"import\s+([^;]*?)\s*from\s*["']([^"']+)["']"#).unwrap() ```

esbuild's minifier drops that space when the next token is `{` (no ASI hazard there), so a minified named import reads `import{EventEmitter as e}from"node:events"` — zero whitespace after `import`. `IMPORT_RE` doesn't match this at all, so `scan_external_imports` never adds `node:events` to `main_imports`, `register_stubs` never registers a stub for it, and V8's static link step fails when it actually tries to resolve the specifier.

This isn't specific to `node:events` — it affects **any** `nodejs_compat` builtin pulled in via a brace import in a minified bundle. That's the normal output shape of `esbuild --minify`, and specifically of `vite build` via `@cloudflare/vite-plugin` (e.g. RedwoodSDK's build output, which is how I hit this).

## Repro

```js // repro.mjs — minimal repro of the exact minified shape esbuild produces import{EventEmitter as e}from"node:events"; console.log(new e()); ```

Deploy this (or any bundle containing an import in this exact shape) with `no_bundle: true` pointed at the file, and `celld dev` fails with the error above. A conventionally-spaced `import { EventEmitter } from "node:events"` works fine — only the space-less brace form breaks.

## Fix

One-character change: `import\s+` → `import\s*` in `IMPORT_RE`. This still requires the literal `import` keyword but no longer requires a trailing space before `{` or `*`. Verified it doesn't change behavior for conventionally-spaced imports.

I have this fixed and tested (3 new unit tests: minified brace import, conventionally-spaced import, default/namespace imports — the first fails without the fix, all three pass with it) on a branch: https://github.com/theophane05/celld/compare/main...theophane05:celld:fix/import-scanner-minified-brace-imports

I tried opening a PR from that branch but repo settings appear to block PR creation from forks (`CreatePullRequest` GraphQL permission error / 404 on the REST create-PR endpoint), so filing this issue with the branch link and full patch instead. Happy to send the diff inline here too if that's easier to act on:

```diff --- a/crates/celld/js/modules.rs +++ b/crates/celld/js/modules.rs @@ -73,7 +73,7 @@ fn is_external(spec: &str) -> bool { /// cost once for the main module and once more for each sibling module of a /// Worker Loader bundle — on every isolate build. static IMPORT_RE: std::sync::LazyLock<regex::Regex> = std::sync::LazyLock::new(|| { - regex::Regex::new(r#"import\s+([^;]*?)\s*from\s*["']([^"']+)["']"#).unwrap() + regex::Regex::new(r#"import\s*([^;]*?)\s*from\s*["']([^"']+)["']"#).unwrap() }); static IMPORT_BRACES_RE: std::sync::LazyLock<regex::Regex> = std::sync::LazyLock::new(|| regex::Regex::new(r"\{([^}]*)\}").unwrap()); ```

## Environment

- celld 0.4.1 (also confirmed present in `main`, same commit as the `v0.4.1` tag) - Repro'd against RedwoodSDK's `vite build` output (`@cloudflare/vite-plugin`) — a bare-bones starter with no Durable Objects/D1/R2, so this hits the very first Worker load, not something usage-pattern specific.

  1. bartlomiejuclosedlast month on GitHub

  2. BA

    Thanks for the report. This is now fixed and will be released in the next version.

  3. bartlomiejureferenced 9c2d299dd6ablast month on GitHub

  4. ryreferenced e519694581dclast month on GitHub

  5. ryreferenced 4250d366aceblast month on GitHub

  6. ryreferenced 3127cf8e307elast month on GitHub

  7. ryreferenced 12d5b6333fe5last month on GitHub