Files
Luke SandbergandGitHub 6344e18ac1 Turbopack: extract inline base64 decode helper to shared @turbopack/base64 module (#92549)
### What?

When Turbopack generates a module using `import foo from './blah' with {type:'bytes'}`, it needs a base64 decode helper. Previously this was inlined into every generated module. This PR extracts it to a shared `@turbopack/base64` module imported via a special import map, and encapsulates the import map registration inside the turbopack crate itself.

### Why?

1. **Deduplication** — The base64 decode helper is shared across all `{type:'bytes'}` imports instead of being duplicated inline in every generated module.
2. **Encapsulation** — The `@turbopack/*` and `@vercel/turbopack-ecmascript-runtime/*` import map aliases are now injected automatically by `ModuleAssetContext::resolve_options` in the turbopack crate. Consumers (next-core, turbopack-cli) no longer need to manually register these aliases in their import maps.
3. **Extensibility** — Future turbopack built-in modules can be added to a single `turbopack_runtime_import_map()` function, with no changes needed in any consumer.

### How?

**Base64 module (`turbopack-ecmascript-runtime`):**
- Added `turbopack/crates/turbopack-ecmascript-runtime/js/src/shared/base64.ts` with `base64Decode()` using ES2024 `Uint8Array.fromBase64` with an `atob()`-based fallback.
- The ES2024 feature check is evaluated once at module load time (top-level const), not per-call.
- The module is marked `"use turbopack no side effects"` for tree-shaking.

**BytesSourceTransform (`turbopack-ecmascript`):**
- Changed `BytesSourceTransform` to emit `import { base64Decode } from '@turbopack/base64'` instead of inlining the helper.

**Import map encapsulation (cycle-breaking refactor):**
- Moved `get_runtime_asset_context` from `turbopack-ecmascript-runtime` → `turbopack` crate, breaking the cyclic dependency so turbopack can now depend on `turbopack-ecmascript-runtime`.
- Changed `get_nodejs_runtime_code` and `get_browser_runtime_code` to accept an `AssetContext` parameter instead of constructing one internally.
- Added `turbopack_runtime_import_map()` to `turbopack-ecmascript-runtime` containing both the `@vercel/turbopack-ecmascript-runtime/*` wildcard and `@turbopack/base64` exact aliases.
- `ModuleAssetContext::resolve_options` now injects this import map automatically.
- Removed `insert_turbopack_dev_alias` from `next-core` and the equivalent block from `turbopack-cli`.

<!-- NEXT_JS_LLM_PR -->
2026-04-10 08:45:37 -07:00

31 lines
658 B
TOML

[package]
name = "turbopack-ecmascript-runtime"
version = "0.1.0"
description = "TBD"
license = "MIT"
edition = "2024"
autobenches = false
[lib]
bench = false
[features]
# enable "HMR" for embedded assets
dynamic_embed_contents = ["turbo-tasks-fs/dynamic_embed_contents"]
# enable test utilities such as `RuntimeType::Dummy`
test = []
[lints]
workspace = true
[dependencies]
anyhow = { workspace = true }
indoc = { workspace = true }
serde = { workspace = true }
turbo-rcstr = { workspace = true }
turbo-tasks = { workspace = true }
turbo-tasks-fs = { workspace = true }
turbopack-core = { workspace = true }
turbopack-ecmascript = { workspace = true }