Add support for primitive WebIDL typed arrays and fix ByteString mapping.

The WebIDL frontend currently does not recognize primitive typed array types (e.g., `Float32Array`, `Uint8Array`) and treats `ByteString` as a byte buffer (`&[u8]` / `Vec<u8>`). This should be changed:
- Accept `Float32Array`, `Float64Array`, `Int8Array`, `Int16Array`, `Int32Array`, `Uint8Array`, `Uint8ClampedArray`, `Uint16Array`, `Uint32Array` as valid WebIDL types and map them to Rust slices (`&[T]`) for arguments and `Vec<T>` for return values, consistent with existing slice support.
- Change `ByteString` to map to `&str` / `String` instead of byte buffers, because ByteString is represented as a JavaScript string per the WebIDL spec. `USVString` should also map to Rust strings (ensure it does; if not, fix it).

All other string types (`DOMString`, `USVString`, `ByteString`) should produce `&str` for arguments and `String` for returns.

The change should be made in the type‑translation logic that converts WebIDL types to Rust types (the wasm‑bindgen webidl crate).

Add support for more slice types in WebIDL


**Title:** Variadic imports lose argument type fidelity; missing span on variadic-attr errors

**Description:**

When using `#[wasm_bindgen(variadic)]` on imported functions, the generated JavaScript shim currently creates an intermediate array, pushes the variadic slice into it, and then invokes the target with `.apply`. This approach can coerce the variadic arguments to strings (and cause other type-related issues), breaking type integrity for integer, floating-point, and `Option` types. The expected behavior is that the generated call preserves the original argument values exactly as a direct `fn(...args)` spread would.

Additionally, if a user accidentally applies the `variadic` attribute to something other than an `extern` import (e.g., a struct field or a Rust export function), the resulting error message does not include a source span, making it difficult to locate the offending code. The diagnostic should point to the exact item that carries the misplaced attribute.

**Steps to reproduce (behavioral summary):**
- Import a function with `#[wasm_bindgen(variadic)]` and integer/float/`Option` arguments; observe that the values received by the JS function are not the original numbers/options.
- Place `#[wasm_bindgen(variadic)]` on a struct field or on a `pub fn`; the compiler error does not highlight the offending item.


**Bug: Global import shadows module import (or vice versa) when they share a name**

When a Rust crate uses `#[wasm_bindgen]` to import a JS function both from a global (e.g. `window.Math.sqrt`) and from a JS module that exports a symbol with the same name or namespace, the generated JavaScript glue can produce incorrect identifiers or cause a runtime `ReferenceError`. In some cases the build fails with an error about conflicting imports; in other cases the error is silent until execution, where the wrong function is called or the binding is undefined.

**Steps to reproduce**
1. Import a function from a global scope:
   ```rust
   #[wasm_bindgen]
   extern "C" {
       #[wasm_bindgen(js_namespace = Math, js_name = "sqrt")]
       fn sqrt_from_global(x: f64) -> f64;
   }
   ```
2. Also import a function from a module that re‑exports or uses the same identifier (e.g., `Math` or a shared namespace):
   ```rust
   #[wasm_bindgen(module = "some_module")]
   extern "C" {
       #[wasm_bindgen(js_namespace = Math)]
       fn func_from_module(a: i32) -> i32;
   }
   ```
3. Call both functions from Rust.
4. Build with `wasm-bindgen-cli`.

**Observed behavior**
The generated JavaScript may assign the same local identifier to both imports, causing one to shadow the other. For example, the `Math` namespace from the global gets overwritten by the module import, so `sqrt_from_global` calls the module’s `Math` object (or vice versa) instead of the real `Math`. In some configurations the build outright fails because the same import name is requested from two different sources.

**Expected behavior**
Global imports (unscoped, implicit) should always be resolved first and keep their original name. Module imports that collide should be renamed internally (e.g., `Math2`) so that both can coexist in the generated JS. The same rule should hold when two different modules export the same namespace or function name: each module's binding should get a unique identifier without interfering with globals or each other.

**Additional context**
This is especially important for crates wrapping web APIs that combine browser globals (like `Math`, `Date`, `JSON`) with user‑defined or npm modules that use the same names. The fix should ensure that any global import retains its exact external name and that module imports are renamed transparently when they would conflict, regardless of the order in which imports are processed.

try to fix global / modulaized import ns conflict (#2057)


**Title:** `usize`/`isize` conversions to `JsValue` produce JS BigInt instead of Number on wasm32

**Background**
On the wasm32 target, Rust’s `usize` and `isize` are 32-bit types.
However, the current `From<usize> for JsValue` and `From<isize> for JsValue` implementations treat them like arbitrary‑precision integers and map them to JavaScript `BigInt` values.
This is inconsistent with how we handle every other 32‑bit integer (`u32`/`i32`), and it contradicts the fact that these types are already represented as regular numbers everywhere else in the bindings (e.g. in slice conversions, and in the type descriptors generated by the `describe` macro).

**Observed symptoms**

1. Calling `JsValue::from(some_usize)` gives a JS `BigInt` rather than a `Number`, so passing it to a JS function that expects a number fails or behaves unexpectedly.
2. Async functions that return `usize` or `isize` are internally converted via `Into<JsValue>`, causing the resulting Promise to resolve with a `BigInt` on the JS side. This breaks any JS code that expects a plain `number` from those exported async functions.
3. Because `PartialEq<usize> for JsValue` and `PartialEq<isize> for JsValue` are also implemented in terms of the `From` conversion, equality checks against `JsValue` will only succeed when the JS value is a `BigInt`, not when it is a `Number`.

**Desired behaviour**

- `From<usize> for JsValue` must produce a JS `Number` (the same way `From<u32>` does).
- `From<isize> for JsValue` must produce a JS `Number` (the same way `From<i32>` does).
- `PartialEq<usize> for JsValue` and `PartialEq<isize> for JsValue` must compare the `JsValue` against the corresponding 32‑bit number, not against a `BigInt`.
- All values that are valid for `u32`/`i32` must round‑trip correctly, including `usize::MAX` (0xFFFFFFFF) and `isize::MIN` (-2147483648).

**Non‑obvious constraints**

- This is a **breaking change** for any code that relied on the old BigInt conversion. This is unfortunate but acceptable because the old behaviour was wrong for the wasm32 target and was inconsistent with the rest of the crate.
- On wasm32 we can safely cast `usize` → `u32` and `isize` → `i32` without loss, so the implementation can be a simple forwarding to the existing `u32`/`i32` conversions.
- The TypeScript type generation (if affected) should reflect that exported functions taking or returning `usize`/`isize` expect/produce `number`, not `bigint`.

**Acceptance criteria**

- Exported Rust functions that accept or return `usize`/`isize` are callable from JS with plain numbers and return plain numbers.
- Exported async functions returning `usize`/`isize` resolve to plain numbers.
- Slice round‑tripping for `&[usize]` and `&[isize]` continues to work (this already uses `u32`/`i32` under the hood).
- Value‑range boundaries (`isize::MIN`, `usize::MAX`) survive a Rust‑to‑JS‑to‑Rust round trip through `JsValue`.

Properly implement `From<usize/isize>` and `PartialEq<usize/isize>` for `JsValue` (#2978)


**Issue: Make `wasmer run` caching test hermetic and timing-independent**

The integration test that verifies the `wasmer run` cache for packages (currently `#[ignore]`) has two issues that make it unreliable and intrusive:

1. **It leaks into the developer’s real `$WASMER_DIR`** – the test shares the global cache directory, so a developer’s local cache state (or other tests running concurrently) can affect the outcome, and the test pollutes the user’s cache.
2. **It detects a cache hit by measuring wall-clock time** – a second run is assumed to be faster if the package was cached, but elapsed-time assertions are inherently flaky and fail under varying load or network latency.

We want the test to be self-contained and deterministic.

**Acceptance criteria**

- The test for package caching **must use an isolated temporary directory** as the `WASMER_DIR` for all `wasmer` invocations, so it never touches the user’s real cache.
- The test **must not rely on timing** (e.g., comparing `Instant::now()` before and after the second run) to prove that caching occurred.
- The test should **start with an empty cache**, run a package download twice, and observe the CLI output to confirm that:
  - The first run produces output that indicates a network lookup / download.
  - The second run produces output that shows the cached result was used **without** hitting the network again.

To enable that observation, the runtime’s registry-cache path should emit a **debug-level log message** when it fulfills a query from the local cache. The test can then enable `RUST_LOG` for the relevant module and inspect stderr for the expected traces.

**Out of scope**
- Do not change the production caching semantics; only add the debug log.
- The test currently resides in `tests/integration/cli/tests/run.rs` and is named `run_test_caching_works_for_packages` – that is the only test that needs to be updated.

Make sure the caching test doesn't use the global $WASMER_DIR


**Title:** `wasmer create-exe` native executables should support `--dir` and `--mapdir` for WASI preopens

**Component(s):** CLI (`create-exe`), WASI C API, `wasmer_wasm.h` generated header
**Type:** Feature request

## Summary
Currently, when a user generates a native executable with `wasmer create-exe`, the resulting binary runs a single hard‑coded wasm program with a fixed set of WASI arguments (for example, a JavaScript snippet evaluated by QuickJS). There is no way to pass `--dir` or `--mapdir` to the native executable to configure WASI preopened directories at runtime. The same flags are supported by `wasmer run` and should work for `create-exe` binaries as well.

## Desired behavior
When a user runs a native executable produced by `wasmer create-exe`:

```
./my_program --dir /some/path --mapdir /guest:/host -- arg1 arg2
```

- The `--dir` and `--mapdir` flags (and their `=` forms, e.g. `--dir=/some/path`, `--mapdir=/guest:/host`) should be consumed by the executable’s startup code and used to configure the WASI environment **before** the wasm module is instantiated.
- All arguments **not** recognized as `--dir` or `--mapdir` should be forwarded to the guest program as WASI `args`.
- If `--dir` is missing its required argument, or `--mapdir` is malformed (missing `:` or directory), the executable should print an error to stderr and exit with a non‑zero status.

Internally this requires:
1. Two new WASI C‑API functions: `wasi_config_preopen_dir` and `wasi_config_mapdir`, mirroring the existing `WasiStateBuilder` methods.
2. Their declarations in the auto‑generated `wasmer_wasm.h` header (they must be exposed when `WASMER_WASI_ENABLED` is defined, and must **not** be filtered out by the Wasm‑C‑API header generation in `build.rs`).
3. The C entry point template used by `create-exe` (`wasmer_create_exe_main.c`) must be updated to parse `argv`, intercept `--dir` and `--mapdir`, call the new WASI config functions, and pass the remaining arguments as guest arguments.

## Non‑visible requirements / invariants
- The existing behavior of `wasmer create-exe` for modules that do **not** use WASI must remain unchanged. The WASI‑specific argument handling should be compiled conditionally (e.g., under a WASI preprocessor define).
- The new C API functions should follow the same error‑reporting pattern as the other WASI config functions (set the last error and return `false` on failure).
- The changes must not break the existing integration tests for the object‑file engine (`compile.rs`) and for `create-exe` (`create_exe.rs`), but those tests should be extended to pass the program arguments through `run_code` (the test helper already supports an `args` parameter but it isn’t used yet).

## Notes
- The `create-exe` template currently ignores `argc`/`argv` entirely; moving to argument‑driven startup is a prerequisite for this feature.
- The `WasiStateBuilder` already provides `preopen_dir` and `map_dir` – we only need to bridge them to C and consume the flags in the entry point.

Add --dir and --mapdir support to native executable


**Title:** Host-imported closures with captured state (non-zero-sized closures) panic or lose captured environment when called from WebAssembly

**Description**
When a user imports a Rust closure that captures variables (i.e., has a non-zero-sized environment) into a Wasmer instance using `Func::new`, two problems occur:

1. **Panic (debug/assertion build):** The import path asserts that the size of the closure is equal to `size_of::<usize>()`, which fails for any closure that captures state larger than a single pointer. The current implementation effectively forbids closures that carry an environment.

2. **Silent failure/wrong results (release build):** If the assertion is removed or bypassed, the captured environment is never properly stored into the runtime’s per-import function context (`FuncCtx`). When the imported function is invoked from inside WebAssembly, the wrapper function cannot recover the original closure, so any captured variables are lost (zero-initialized or garbage).

**Expected behavior**
- `Func::new` must accept any `'static` Rust closure, including those that capture an arbitrary-sized environment (e.g., a counter, a vector, a reference).
- When such a closure is imported into a WebAssembly module and called from that module, the closure must execute with its original captured environment intact and produce the correct result.
- The fix must preserve existing behavior for function pointers and zero-sized closures (which should still work without overhead).
- The behavior must be consistent for both `ImplicitVmCtx` (closures that do not take a `&mut vm::Ctx`) and `ExplicitVmCtx` (closures that do take `&mut vm::Ctx` as their first parameter).

**Non-obvious constraints**
- The captured environment must be stored in a way that is compatible with the existing VM ABI: the environment pointer (`func_env` in `vm::FuncCtx`) must be set to point to the boxed closure, and it must be `None`/null for function pointers and zero-sized closures.
- When the import is converted into an `Export`, the `Context::External` variant must hold the `func_env` pointer (for closures with an environment) instead of always using `Context::Internal`. This pointer must survive as long as the WebAssembly instance.
- The `ExternalFunction::to_raw` trait method must be changed to return both the function pointer and an optional environment pointer, and its implementations must correctly heap-allocate the closure when `mem::size_of::<Self>() > 0` and set the environment pointer accordingly.
- All these changes must not break existing tests for imported functions (function pointers, zero-sized closures, closures with vmctx access, trapping imported functions).

**Affected public API surface (observable)**
- `wasmer_runtime_core::typed_func::Func::new`
- The `ExternalFunction` trait (callers that implement it)
- The `FuncCtx` and `ImportedFunc` structures (field visibility changes may be required to enforce invariants)

**Edge cases to handle**
- Closures that capture multiple variables (large environment).
- Closures that capture both data and a reference (lifetime `'static` constrained by `F: ExternalFunction<...>`).
- Closures used with both sync and trap-returning signatures.
- Interaction with `vm::Ctx`-aware closures (the `vmctx` pointer must still be correctly set alongside the environment pointer).


When running a WASI module from a `.webc` container with mapped host directories (e.g. `--mapdir /host/path:/guest` or via `WasiRunner`'s `mapped_dirs`), the host directories are not visible inside the WebAssembly sandbox. The container's own filesystem is exposed, but any explicitly mapped guest paths are missing. The expected behavior is that the module can read/write files under the mounted guest path, with the container filesystem still accessible under `/`. Additionally, the root directory `/` should be preopened so the module can traverse the entire merged filesystem.

**Acceptance criteria**
- When a `.webc` container is executed with one or more `--mapdir` parameters, each mapped host directory must be accessible inside the WASI environment at the specified guest path.
- The container's existing files (e.g. from its volumes) must remain accessible under `/`, side by side with the mounted directories.
- The WASI environment's preopen list must include `/` (or the root) so that the module can discover and traverse both container files and mounted directories.
- This should work whether the module is a standard WASI command (via the WASI runner) or a WCGI handler, matching the existing mounted-directory behavior for bare `.wasm` files.


**Title:** Remove unsound `'static` lifetime transmutes in the Cranelift backend and harden the compilation pipeline

**Background**
The Cranelift backend’s `ModuleCodeGenerator` implementation currently uses an `unsafe` `transmute` to extend borrow lifetimes to `'static` when building a `FunctionBuilder` inside `next_function`. This is unsound and can lead to undefined behavior or memory corruption. Additionally, the module metadata (`ModuleInfo`) is unwrapped too early from its `Arc`, which can lead to use‑after‑free if any part of the compile pipeline still holds a reference to the info.

**Requested changes**

1. **Eliminate the lifetime hack**
   Refactor `CraneliftFunctionCodeGenerator` so that it no longer stores a `FunctionBuilder<'static>` produced via `transmute`. Instead, own all the pieces necessary to construct a `FunctionBuilder` on demand, and rebuild it inside method calls that need it (`feed_local`, `feed_event`, `finalize`, etc.). The builder must never outlive the function it operates on.

2. **Fix `ModuleInfo` lifetime**
   Ensure that `ModuleInfo` stays inside an `Arc` until the final module is fully constructed. The current early unwrap in `read_module` should be removed, and callers must accept the `Arc` accordingly.

3. **Add early Wasm validation**
   Introduce a validation step at the start of the streaming compilation. Use `wasmparser::ValidatingParser` to scan the entire Wasm binary for structural errors before any backend‑specific code generation runs. If validation fails, bail out with a `ValidationError` immediately; do not rely on the backends to detect invalid inputs.

4. **Backend‑agnostic spec‑test example**
   The example test `test.rs` currently hardcodes `CraneliftCompiler`. Replace the hardcoded dependency with a `get_compiler` helper that selects the compiler at runtime based on enabled feature‑flags (`clif`, `llvm`, `singlepass`). This allows the test to be used as a sanity‑check for any compiled backend.

**Constraints and invariants**
- No `unsafe` transmutes or lifetime‑extension tricks may remain in the function‑code‑generation path.
- `FunctionBuilder` must be constructed from owned or scope‑confined borrows; storing it across method calls on a mutable struct is acceptable only if the lifetime guarantees are provably correct without `unsafe`.
- The validation pass must run **before** any part of the backend code generator starts, and its error messages must be compatible with the existing `CompileError::ValidationError` variant.
- The `Arc` containing `ModuleInfo` must be correctly cloned when shared, and must not be forcibly unwrapped until the point where no further sharing is possible.

**Acceptance criteria**
- The Cranelift backend compiles and passes the WebAssembly spec test suite without any unsafe lifetime transmutes.
- A deliberately malformed Wasm binary triggers a `ValidationError` with a descriptive message, rather than an internal compiler error or silent miscompilation.
- The `test.rs` example succeeds when compiled with any of the three backend feature‑flags.

Update lifetime of function builder references


Add a `Func::new_polymorphic` constructor to the `runtime-core` crate’s `typed_func` module that builds a host function from a runtime-provided `FuncSig` and a closure `Fn(&mut Ctx, &[Value]) -> Vec<Value>`. The method must work by generating an appropriate call-info trampoline via `TrampolineBufferBuilder`, marshalling raw `u64` arguments into a `Vec<Value>` guided by the signature, calling the closure, and converting the returned `Vec<Value>` back.
Gate the implementation under `#[cfg(all(unix, target_arch = "x86_64"))]`. The trampoline must treat the first argument slot as the implicit `vmctx` pointer (matching the existing convention for host-import trampolines) so the closure receives the VM context.


When a WebAssembly package that contains multiple commands is loaded via `--uses` (or `WasiEnvBuilder::uses()`), those commands should appear in `/bin` so they can be executed by the program. This works correctly with the sandbox filesystem (`TmpFileSystem`), but does not work when a backing filesystem is provided (e.g., the host filesystem or a custom `FileSystem`). The package's own filesystem (`webc_fs`) should also be merged into the root filesystem regardless of the filesystem backend.

Ensure that for any `WasiFsRoot` variant:
1. the package’s filesystem contents are merged (as already done for sandbox),
2. each command's bytes are written to `/bin/<command_name>`,
3. and the `BinFactory` is populated so that `get_binary` can later resolve them.

The fix should handle the case where the backing filesystem does not support the sandbox-specific shortcut (`insert_ro_file`).

Make sure packages from "--uses" are loaded into "/bin"


```
Improve test suite robustness to available compile backends.

The tests currently assume a specific compiler backend (often the default) and break when only a subset of backends are compiled in. They should instead be backend-agnostic and exercise every backend that is enabled at build time.

To support this, the public `Module` API needs a constructor that accepts a compiler instance, so callers can compile a module with an explicitly chosen backend rather than only the default. The existing `compiler_for_backend` function provides a way to get a compiler for a `Backend`, but no `Module` constructor accepts a compiler directly.

Tasks:
1. Add a `Module` constructor (e.g., `new_with_compiler`) that takes a byte slice and a `Box<dyn Compiler>`, and returns a compiled `Module`.
2. Update the test helper infrastructure so that test cases can be declared once and automatically instantiated for each enabled backend (singlepass, cranelift, llvm) using `compiler_for_backend`. Remove the pattern of separate `mod` blocks per backend in `imports.rs`. Ensure the same test logic is executed with the appropriate compiler for each backend feature flag.
3. Migrate existing tests that currently use the default compiler (`Module::new`, `compile`, etc.) to use the new backend-aware runner. This includes tests in `high_level_api.rs`, `imports.rs`, and `wasi_serialization.rs`.
4. Remove obsolete test files `override.rs` and `spectest_semantics.rs`; the former is redundant and the latter is superseded by WAST-based spec tests (stack-overflow test is now a WAST file elsewhere).
5. The test crate must compile and run correctly when zero backends are enabled or when only a subset is selected. Remove static compile errors that assert at least one backend must be present.
6. Clean up dead-code warnings in test utilities (`get_backend_from_str`, `StdioCapturer`) with `#[allow(dead_code)]` as needed.
```

Improved tests to use available compilers


**Title:** Reduce retained memory by freeing host environment initializers after instance initialization

**Background**
When an imported function carries a host environment (i.e., a `WasmerEnv`), the runtime must call `init_with_instance` on that environment after the Wasm instance is created. The information needed for this call—a function pointer and a host environment pointer—is stored in the `Imports` struct inside the field `host_function_env_initializers`. This data is only used during `InstanceHandle::new` (specifically, within `initialize_host_envs`). After that it is never read again, yet the entire `BoxedSlice` and all its entries remain allocated for the lifetime of the instance.

**Acceptance criteria**

1. **One-shot consumption**
   `host_function_env_initializers` is consumed (moved out) when the import-initializer thunks are extracted, and the storage is released immediately after use. After extraction the field must be logically empty; any subsequent attempt to re‑extract should return an empty collection without undefined behavior.

2. **Encapsulation**
   The logic that pairs each function’s initializer function pointer with its host environment pointer (including the correct handling of `null` for functions that don’t have a host env) lives on `Imports` rather than being duplicated at the call site in the artifact instantiation code.

3. **Type clarity**
   The raw function-pointer type `fn(*mut c_void, *const c_void) -> Result<(), *mut c_void>` that appears repeatedly as the import-initializer signature is given a descriptive shared alias so that changes to the signature propagate automatically and the intent is clearer.

4. **Memory reduction**
   After `InstanceHandle::new` completes construction, no memory is wasted holding the already-used initializer function pointers or the now-useless `BoxedSlice` wrapper. The runtime’s steady-state memory footprint for a fully initialized instance must no longer include the leaked host-function initializer data.

5. **Correctness invariants**
   - Extracted thunks are passed to the instance constructor exactly as before, preserving the order and pairing.
   - The `Imports::none()` and `Imports::new()` constructors remain usable; they transparently reflect the fact that the field is initially populated and later deleted.
   - The `initialize_host_envs` logic on `InstanceHandle` is unchanged except that it may rely on a helper from `Imports` for the extraction; the behavior must remain identical for both imported functions *with* and *without* a host environment.

6. **Collateral improvement (tests)**
   Tests that manually implement `WasmerEnv` with a trivial `init_with_instance` (just returning `Ok(())`) should be updated to use the `WasmerEnv` derive macro where possible, so that they continue to compile after any trait-related changes and serve as a compile‑time check that the derive remains adequate.

**Non-goals**
- Changing the signature or semantics of `init_with_instance` itself.
- Altering how host environments are attached to imported functions (`ExportFunction.function_ptr` remains the same).
- Modifying serialization, resolving, or the public API of `Imports` beyond the addition of a one‑shot extraction method.

Clean up code, reduce memory usage, improve correctness


**Title:** `--precompiled-atom` mis-parses three-part `ATOM:PREFIX:PATH` format, swapping prefix and path

**Description**
When a user passes a three-part `--precompiled-atom` value of the form `ATOM:PREFIX:PATH` (where `PREFIX` is a sha256 or literal prefix and `PATH` is the path to a precompiled object file), the CLI incorrectly treats the path as the prefix and the prefix as the path. This leads to obviously wrong behaviour: the prefix is used as a file path (causing file-not-found errors or silent corruption), while the real path is stored as the prefix.

The intended CLI contract for `--precompiled-atom` is:
- `ATOM:PATH` — no prefix, just atom name and object path
- `ATOM:PREFIX:PATH` — atom name followed by a prefix (e.g., a sha256) and then the object path

Currently the three-part form is being parsed as `ATOM:PATH:PREFIX`, which is the reverse of the documented intent.

**What needs to be fixed**
1. **Parsing logic:** Update the internal splitting so that the three captured pieces are `atom`, `prefix`, `path` in that order.
2. **Regex / splitting robustness:** The split must handle file paths that themselves contain colons, especially absolute Windows paths (`C:\...` or `\\?\...`) and Unix-style paths with drive-letter colons the tool might encounter. The regex that extracts the segments should be adjusted so that only the *first* colon separates the atom from the remainder, and an optional second colon separates the prefix from the path; the path must then consume the rest of the string even if it includes additional colons.
3. **Error messages:** Any error message that prints the expected format must show `ATOM:PREFIX:PATH` (or `ATOM:PATH`), not `ATOM:PATH:PREFIX`.

**Acceptance criteria (observable)**
- Passing `--precompiled-atom myatom:abc123:/some/object.o` results in:
  - atom = `myatom`
  - prefix = `abc123`
  - path = `/some/object.o`
- Passing `--precompiled-atom myatom:/some/object.o` (no prefix) continues to work correctly.
- Windows-style path with colons such as `myatom:abc123:C:\temp\obj.o` is handled correctly and the path includes the drive letter.
- The `--help` or error output for invalid usage describes the format as `ATOM:PREFIX:PATH` or `ATOM:PATH`.


**Title:** DWARF EH pointer decoding crashes on null landing-pad offset (nested C++ exceptions on macOS/Wasix)

**Description**
When running a C++ program that uses nested `try`/`catch` blocks under the Wasix runtime (macOS hosts), the runtime crashes with a memory access violation. The crash originates in the DWARF exception-handling personality function when it decodes an encoded pointer that represents `null` (a relative encoding with an offset of zero).

The DWARF Exception Handling specification states that for relative encodings, a raw value of zero denotes a null pointer; no base adjustment or indirect dereference should be performed. The current implementation adds the base address to the zero offset (producing a non-null pointer) and then tries to dereference it indirectly, causing the crash.

**Expected behavior**
- A C++ program with nested exceptions (an inner `catch` that re-throws and an outer `catch` that handles the re-thrown exception) should execute without crashing.
- The program should output `inner 1` and `outer 2` (in that order) and exit with code `0`.
- Existing single-level and shared-library exception tests must continue to pass.

**Acceptance criteria**
1. In the DWARF EH pointer decoder (`read_encoded_pointer`), when a relative encoding yields an offset of zero, the result must be a null pointer and no indirect load may be attempted.
2. A new Wasix exception regression test is added that builds and runs a C++ program exercising nested exceptions (inner re-throw, outer catch).
3. The test harness successfully locates a compatible Wasix sysroot on a developer machine where `wasixccenv` is available (so that the new test can actually build).
4. All existing `exception_tests` continue to pass.

fix(macos): Fix a bug in EH info decoding (#6285)


The `cargo build-wasmer` and `cargo build-capi` aliases defined in `.cargo/config` currently do not perform any actual compilation; they just print a status message and exit.

**Steps to reproduce**
1. Ensure the repository has the current `.cargo/config` aliases set up (they already exist).
2. Run `cargo build-wasmer` or `cargo build-capi` with or without the `COMPILERS` environment variable.
3. Observe that no build output appears and no binary is produced – only a line like “build wasmer, compilers = …” is printed.

**Expected behavior**
- `cargo build-wasmer` should invoke a release build of the Wasmer CLI crate located at `lib/cli/Cargo.toml`.
- `cargo build-capi` should invoke a release build of the C API crate located at `lib/c-api/Cargo.toml`.
- Both commands should respect the `COMPILERS` environment variable, which can contain a comma-/space‑separated list of compiler backends (e.g., `cranelift,singlepass`). When `COMPILERS` is not set, the default should be `cranelift`.
- For the C API specifically, if the user requests `llvm` as a compiler, it should be silently ignored because the C API does not support the LLVM backend.
- The builds should correctly propagate stdout/stderr so that users see build progress and error messages. If the underlying `cargo build` fails, the task should exit with a non-zero status and report a clear error.
- The builds should not require any filesystem, network, or environment access beyond what `cargo build` normally needs (unless those are explicitly enabled by feature flags).

**Impact**
Developers rely on these short aliases to quickly compile the CLI and the C API; currently they are useless and developers must remember the exact manifest paths and feature combinations. Filling in the actual build logic would restore the intended developer workflow.

Add tasks for cargo build-wasmer and cargo build-capi


```
Fix: PluggableRuntime should own a concrete Engine, not an Option, to prevent creating a new default engine on every engine()/new_store() call.

Currently PluggableRuntime stores engine: Option<Engine>. When it's None, both engine() and new_store() each call Engine::default(), creating a new engine instance per call. This leads to many redundant default engines. The runtime should instead always hold an Engine, initialized to Engine::default() on construction, so a single default engine is reused. The set_engine setter should accept a plain Engine (not Option). Update all callers accordingly: remove the Some(…) wrapper from set_engine arguments. Callers that previously called set_engine(Some(Engine::default())) can drop the set_engine call entirely, because the runtime already starts with the default engine.
```

Fix PluggableRuntime creating many engines when one is not provided to it directly


```
Title: Implement `Exportable` for `&T` (borrowed extern references)

Background:
- The `Exports::get` method allows retrieving individual exports from an `Exports`
  map by name. It is generic over any type `T: Exportable<'a>`, where the
  `Exportable` trait provides `to_export` and `get_self_from_extern`.
- Currently `Exportable` is implemented for owned extern types:
  `Function`, `Global`, `Memory`, `Table`, and `Extern`. Users can call
  `exports.get::<Memory>(name)` and get a `Memory`, but they cannot get a
  reference `&Memory` (nor `&Function`, etc.) without cloning the underlying
  resource.

Problem:
- In several API scenarios it is desirable to obtain a reference to an extern
  (e.g., `&Memory` or `&Function`) rather than moving/cloning the value out of
  the exports. The `Exports::get` method's signature supports this—nothing in
  its implementation prevents it—but the `Exportable` implementations for
  borrowed types are missing.

Request:
- Add `Exportable<'a>` implementations for `&'a Function`, `&'a Global`,
  `&'a Memory`, `&'a Table`, and `&'a Extern`. These implementations should:
  - `to_export` produce the same `Export` as the corresponding owned type (no
    unnecessary clones of the underlying raw export handles).
  - `get_self_from_extern` extract the reference from an `Extern` enum without
    cloning; it should return an `Err(ExportError::IncompatibleType)` if the
    extern variant does not match.

Constraints:
- The implementations must be consistent with the existing owned ones (i.e.,
  produce identical `Export` values where possible).
- `get_self_from_extern` for `&'a Extern` should simply return the inner
  reference—no cloning needed.
- The `to_export` for `&'a Extern` will need to delegate to the appropriate
  inner type's `to_export` to avoid code duplication.

Acceptance Criteria:
- `Exports::get::<&Memory>(name)` compiles and returns a reference to the memory
  instance stored in the exports map.
- Similar for `&Function`, `&Global`, `&Table`, and `&Extern`.
- No existing API is broken; the new impls coexist with the owned ones without
  ambiguity.
```

Implement `Exportable` for `&T`s too (for some `T`)


We need a transparent filesystem wrapper that logs every VFS operation (read_dir, create_dir, remove_dir, rename, metadata, remove_file, open, and all file-I/O calls) at `tracing`'s trace level. The wrapper should implement the `FileSystem` trait and delegate to an inner filesystem while logging method names, paths, and errors. Make it publicly available from the VFS crate.

Once that is in place, update the integration tests for `wasmer run-unstable` (in `tests/integration/cli/`) so they can use this tracing when `RUST_LOG` is set, which will help future debugging of filesystem issues. Ensure the trace logger is wired into the tests' environment setups.

While working on this, we also want to enable a previously disabled test for running Python from a webfs file that also mounts a host directory. The test was ignored due to filesystem access limitations that are now resolved. Enable it, and fix any failures it exposes—for example, Python may try to write `.pyc` files on import; you may need to pass `-B` to suppress bytecode generation so the test passes cleanly.

Added a tracing filesystem and more logs


```markdown
**Title:** Delegate Emscripten instance startup to the emscripten library

**Background**
The generic Wasm runner (`src/webassembly/mod.rs`) currently contains Emscripten-specific logic: it decides to call `_main` instead of `main`, marshals command-line arguments into the instance's memory (string copying, argv array construction), and invokes `_main` with the correct signature. This ABI-specific code does not belong in the general runner; it should live inside the `wasmer_emscripten` library.

**Request**
Move all Emscripten‑aware instance startup and argument marshalling out of the generic runner into the `wasmer_emscripten` crate. The emscripten library should expose a **public function** that accepts a compiled module, an instantiated instance, a module path, and string arguments, and handles the entire Emscripten startup sequence (set up runtime state if needed, copy args into memory, build the argv array, call `_main` with the correct signature).

The generic `run_instance` in `src/webassembly/mod.rs` should still detect whether a module is Emscripten (via the existing `is_emscripten_module` helper). When it is, it should delegate entirely to the new emscripten entrypoint. When it is not, it should simply call the standard `main` export. No Emscripten‑specific code (argument marshalling helpers, explicit `_main` calls) should remain in the generic runner.

**Testing considerations**
The Emscripten integration test macros (notably `assert_emscripten_output` in `lib/emscripten/tests/emtests/_common.rs`) currently call `instance.call("_main", &[])` directly, bypassing the new entrypoint. Update that test helper to use the new public function so that the test path matches the real runtime’s code path. The commented‑out `start_instance` calls should be superseded by this.

**Constraints / edge cases**
- `_main` may have different signatures; the implementation should gracefully handle both `() -> ()` and `(i32, i32) -> ()` (the latter is the standard `(argc, argv)` entry). Other signatures should result in a clear error.
- The string copying and array creation must work with the instance’s memory (calling `_malloc` from the module) and must be safe even when the module’s memory is zero‑sized or the allocation fails.
- The new entrypoint must be usable from outside the crate (i.e., `pub fn`) and should not assume any additional global state beyond what is provided.

**Desired outcome**
A clean separation where the emscripten library owns all aspects of launching an Emscripten‑compiled module, and the generic runner only acts as a dispatcher.
```

Move the em specific run_instance code into em lib


When webpack is used programmatically and wrapped in a promise, missing modules or other fatal compilation errors should be handled intuitively so that `async`/`await` callers don’t need to manually check `stats.errors` in all cases.

**Acceptance criteria**

1. **`bail: true` with promise wrapper**
   Given a webpack configuration with `bail: true` and an entry that cannot be resolved (e.g. a missing file or a module that requires a nonexistent file):
   - Calling `compiler.run()` wrapped in a `new Promise` should **reject** the promise with a `ModuleNotFoundError` (or equivalent) that includes the original resolution error message.
   - The rejection must happen even if the error is captured internally and would otherwise be reported via `stats.errors`.

2. **Watch mode with promise wrapper**
   Given a webpack configuration using `watch: true` (or `compiler.watch`) and an unresolvable entry:
   - The promise wrapping the watching call should **resolve** with a `Stats` object, not reject.
   - The `Stats` object must contain the compilation error(s) (e.g. `ModuleNotFoundError`) so the caller can inspect them without an unhandled promise rejection.
   - Closing the watcher should work normally after stats are obtained.

3. **General contract**
   - When `bail` is `false` (or not set), the promise should resolve, and errors should be available in the returned stats—consistent with the callback-based API.
   - Error objects returned or thrown must be identifiable (e.g. `name` matches `"ModuleNotFoundError"`) and preserve the original error details.

test(Compiler): Promisifed webpack returns errors as a return value


Delegated modules (such as those provided by `DllReferencePlugin`) do not participate in the standard export‑flagging pipeline. Instead of reporting their exports to the dependency‑graph‑based `FlagDependencyExportsPlugin`, they override `this.usedExports` and `this.providedExports` directly during `build()`. This bypass causes downstream optimizations that rely on the exported‑names analysis – most visibly `ModuleConcatenationPlugin` – to either fail or produce incorrect output when used together with a DLL reference that declares concrete named exports (e.g., a harmony module with a known `default` export).

## Acceptance Criteria
1. Delegated modules must have their provided exports evaluated through the same `FlagDependencyExportsPlugin` flow as normal modules, so that other plugins consistently see export information.
2. The exported names from a delegated module must be derived from the delegate data (a set of names, or `true` to indicate “all exports”). When the delegate data specifies an array (e.g., `["default"]`), only those exports should be visible to consumers; when it specifies `true`, the module must be flagged as providing all exports.
3. The fix must not alter the runtime output or introduce any additional runtime code. The new mechanism should be purely metadata‑level.
4. Using `DllReferencePlugin` in combination with `ModuleConcatenationPlugin` (or other export‑aware optimizations) should produce correct concatenated output with intact references, including watch‑mode rebuilds.
5. No user‑facing APIs or configuration keys should change. Existing delegate data formats (including `exports: true` and `exports: [...]`) must remain valid.

## Implementation Guidance
- Introduce a dependency similar to a null dependency that carries the module’s export information and is processed by `FlagDependencyExportsPlugin`. This dependency must implement `getExports()` to report the export set, and `getReference()` to link back to the origin module with `importedNames: true`.
- During the `build()` of `DelegatedModule`, add this dependency *instead* of directly setting `this.usedExports` and `this.providedExports`.
- Plugins that set up the compilation (`DelegatedPlugin`, `DllReferencePlugin`) must register a `NullFactory` for this dependency so the compiler knows it requires no code generation.

integrate the delegated module better into the exports flagging process


**Title:** When `output.module` is enabled for node targets, externalize built-in modules as bare `import` declarations

### Problem
Currently, when `experiments.outputModule` is set and `output.module: true` is configured with a node target (e.g., `target: "node"`), the generated output often fails to externalize Node.js built-in modules using proper ESM syntax. Instead, the output may still contain `require()` calls or emit imports with the `node:` prefix (`import fs from "node:fs"`). This occurs even though Node.js ESM supports bare specifiers for built-ins (e.g., `import fs from "fs"`), and having the `node:` prefix unnecessarily ties the output to a specific protocol.

A key limitation is that the `NodeTargetPlugin` only uses the `"module-import"` style when the compiler’s platform is neither explicitly Node nor web (`compiler.platform.node === null && compiler.platform.web === null`). In practice, when targeting Node.js, the platform is often set, which causes the plugin to fall back to `"node-commonjs"`, resulting in `require` calls or `node:`-prefixed imports even when ESM output is requested.

### Desired behavior
When `output.module: true` is enabled (via `experiments.outputModule`), the node target should automatically externalize all Node.js built-in modules using bare `import` statements, **regardless of any platform-specific compiler settings**. Specifically:

- Output should contain `import fs from "fs"`, **not** `require("fs")` and **not** `import fs from "node:fs"`.
- The behavior must cover the full list of Node.js built-in modules (`assert`, `buffer`, `path`, `url`, `module`, …) as well as subpath imports (e.g., `stream/web`, `timers/promises`) when available in the target Node.js version.
- The existing `NodeTargetPlugin` type option `"module-import"` already produces the desired bare-import style; the change should simply select this type whenever `output.module` is true, removing the extra platform guards that currently block it.

### Relevant configuration keys / reference points
- `output.module` (true/false) – enables ECMAScript module output.
- `experiments.outputModule` – required to allow `output.module`.
- `target: "node"` (or `"nodeX.Y"`) – the compilation target.
- `NodeTargetPlugin` – responsible for marking Node built-ins as externals; its constructor accepts a type (`"node-commonjs"` or `"module-import"`).

### Acceptance criteria
Given a webpack configuration with:
```js
module.exports = {
  target: "node",
  experiments: { outputModule: true },
  output: { module: true }
};
```
and a source file that imports a Node built-in, e.g.:
```js
import fs from "fs";
```
the emitted asset should contain:
```js
import fs from "fs";
```
and **must not** contain `require("fs")`, `import fs from "node:fs"`, or any bundled polyfill for that module.

This should hold true for all built-in modules listed by `require("module").builtinModules` on the Node version used at runtime, and also for stable subpath imports (e.g., `stream/web`, `fs/promises`) when the Node version supports them.

feat: improve rendering node built-in module for ES modules output


**Title:** MultiCompiler parallelism and dependencies are not respected when using `invalidate`

**Observed behavior:**

When watching a multi-compiler build that uses `parallelism` or `dependencies` between compilers, calling `watching.invalidate()` triggers a rebuild that ignores those settings.

- **`parallelism`:** With `parallelism: 1`, after `invalidate()` both compilers start compiling simultaneously rather than serially.
- **`dependencies`:** When a compiler declares `dependencies: ["another"]`, after `invalidate` the dependent compiler starts before its dependency finishes compiling.
- **Callbacks:** If an error occurs during the `done` hook or while storing build dependencies, the watcher’s callback list is not properly drained. This leads to missing calls to `handler` or callbacks not being invoked at all.

**Expected behavior:**

- After `watching.invalidate()`, the rebuild must honour the same concurrency limits as the initial watch build: at most `parallelism` compilations should run concurrently, and a compiler must wait for all its declared dependencies to finish before it starts.
- The `done` hook, `storeBuildDependencies`, and any error path must call all outstanding callbacks (both from `watch` and from `invalidate`) exactly once, passing the error or result as expected.

**Impact:**

This breaks build order guarantees and concurrency control. When compilers depend on each other’s outputs or when limited parallelism is required to avoid resource exhaustion, the current behaviour can produce incorrect artifacts, race conditions, or flaky rebuilds.

**Possible areas to fix:**

- The graph‐scheduling state machine in `MultiCompiler._runGraph` does not properly handle state transitions after invalidation: a node that should wait for dependencies may be enqueued prematurely, and a node that is currently queued may be started even if its parents have not finished.
- `Watching._done` may discard the callback array when an error occurs after the `done` hook, preventing the original callers from receiving the error.
- The `Watching.invalidate` method may not call `_onChange()` before `_invalidate()`, which could leave the watcher in a blocked state that never unblocks, especially when combined with dependencies.

respect multi compiler `dependencies` and `parallelism` when using `invalidate`


Fix the inner graph optimization to handle circular references without infinite loops or stack overflows. When flattening the graph to terminal nodes, if a node’s value set includes itself (directly or indirectly), the algorithm must not expand recursively into that set forever. Instead, it should skip the self-reference and correctly propagate only reachable terminal states through the cycle, so that exports reachable exclusively via dead cyclical paths are marked as unused.

fix handling of circular references in the inner graph


When `experiments.topLevelAwait` is enabled, bundling a module that contains a top-level `await` whose execution is conditionally unreachable (for example, `false && await something` or `condition && await something` where the condition is falsy) causes the entire module to never resolve. The application hangs indefinitely, even though the module body did not actually await any promise and the exported value was determined synchronously.

The async module runtime must detect that no `await` expression was evaluated during module execution and still complete the module initialization. The module should resolve with its exports just as it would if the unreachable `await` were absent, producing correct values for dependents without deadlocking the module graph.

Acceptance criteria:
- A top-level `await` inside a short-circuit branch that is never taken does not prevent the module from resolving.
- The module’s exports are available to other modules, and the application does not hang.
- The fix applies to any form of conditional top-level `await` (logical and, logical or, ternary, optional chaining, etc.) where the `await` operand is not evaluated.
- The runtime change must not regress behavior for modules that actually execute a top-level `await`.


**Title:** Library output + runtimeChunk + node target: missing `__webpack_require__` in runtime chunk

**Description**
When using a library output target (e.g. `libraryTarget: "commonjs2"`) together with `optimization.runtimeChunk` and a Node.js-like target (`target: "node"`), the generated runtime chunk does not contain the `__webpack_require__` function. This causes the startup entrypoint to fail at runtime with a `ReferenceError: require is not defined`.

Two issues contribute:

1. The `RuntimeGlobals.startupEntrypoint` runtime module does not declare a dependency on `RuntimeGlobals.require`. As a result, when the runtime chunk only serves the startup entrypoint code, the require function is omitted.
2. In `CommonJsChunkFormatPlugin`, the code that builds the entry wrapper for library outputs with runtime chunks manually constructs the startup calls and appends them directly to the entry source, bypassing the `renderStartup` compilation hook. This prevents plugins (e.g. those inserted by `NodeTargetPlugin` or custom ones) from wrapping or adjusting the startup sequence, which can lead to missing runtime references and inconsistencies with other chunk types.

**Expected Behavior**
- The runtime chunk must include `__webpack_require__` whenever `startupEntrypoint` is used, irrespective of the output library configuration.
- The startup source for library + runtimeChunk combinations should be routed through the `renderStartup` hook, aligning it with the behaviour for regular (non-library) chunks.

**Steps to Reproduce**
1. Configure webpack with `entry: './src/index.js'`.
2. Set `output.libraryTarget: "commonjs2"` (or the equivalent `output.library.type: "commonjs2"`).
3. Enable `optimization.runtimeChunk: "single"`.
4. Set `target: "node"`.
5. Build and attempt to `require()` the main output file in Node.js.
6. Observe `ReferenceError: require is not defined` triggered by the startup entrypoint call.

fix regression when combining library + runtimeChunk + node target


Default `resolve.extensions` apply to all dependency types, causing non-JS resolutions (e.g. CSS, assets) to match `.js`, `.json`, `.wasm` files unintentionally. Move the default JS extension list (`.js`, `.json`, `.wasm`, and `.mjs` when `experiments.mjs` is enabled) from the global `resolve.extensions` into `resolve.byDependency` for every JavaScript dependency type (`commonjs`, `esm`, `amd`, `loader`, `undefined`, `unknown`). The top-level `resolve.extensions` must become an empty array. New non-JS dependency types added in the future should not inherit these JS extensions.

Only apply default js extensions when using a JS dependencyType


# Bug: `[contenthash]` in output filename breaks when the compilation has no async chunks

**Affected versions:** webpack 2.x / 3.x
**Component:** `TemplatedPathPlugin`

## Observed behavior
When `[contenthash]` is used in `output.filename` (or `output.chunkFilename`) and the build **does not produce any async chunks**, the compilation fails with an error like:

```
TypeError: Cannot read property 'javascript' of undefined
```

The failure occurs in `TemplatedPathPlugin` when it tries to read `chunk.getChunkMaps(true).contentHash.javascript` to feed into the content hash computation. If there are no async chunks, the `contentHash` map may not contain a `javascript` entry at all, so the lookup returns `undefined`.

## Steps to reproduce
1. Create an entry module that does **not** import anything dynamically (no `import()`, `require.ensure`, or async AMD require).
2. Set `output.filename` to a pattern containing `[contenthash]`, e.g.:
   ```js
   output: {
     filename: 'bundle.[contenthash].js'
   }
   ```
3. Run webpack.

## Expected behavior
The build should succeed. A content-based hash should be computed for the main chunk and inserted into the filename, even when there are zero async chunks.

## Impact
- Any project that uses `[contenthash]` for cache-busting **without** code-splitting is broken.
- The only workaround is to avoid `[contenthash]` entirely or to introduce a dummy dynamic import, which is not realistic.

## Suggested fix
The hash update inside `TemplatedPathPlugin` should treat a missing `contentHash.javascript` as an empty object (`{}`) rather than trying to stringify `undefined`. This ensures the hash is always computed from a well-defined value and prevents the crash.

The relevant code section (where `REGEXP_CONTENTHASH_FOR_TEST` is matched) should fall back to `|| {}` when the property is absent.

fix bug without async chunks, add more tests


Using `webpack.optimize.ModuleConcatenationPlugin` together with Hot Module Replacement breaks hot updates. When a module is concatenated into a larger scope-hoisted bundle, HMR can no longer replace it individually because the module has lost its own wrapper and boundary. Updates silently fail to apply, or the console shows errors about missing modules or internal HMR state.

Steps to reproduce:
1. Configure webpack with `new webpack.optimize.ModuleConcatenationPlugin()` and `new webpack.HotModuleReplacementPlugin()`.
2. In a module, call `module.hot.accept("./some-dep", ...)` or `module.hot.decline(...)`.
3. Trigger a hot update for that dependency.

Expected behavior:
Modules that use `module.hot.accept` or `module.hot.decline` must remain as standalone modules in the bundle so that HMR can correctly swap them out. The concatenation plugin should detect any module containing HMR accept/decline dependencies and bail out of concatenating that module, preserving its own module boundary.

Actual behavior:
The module is hoisted into a `ConcatenatedModule`. When a hot update arrives, the runtime cannot locate the original module ID or fails to invoke the accept handler properly because the module does not exist as an independent chunk/module in the output. This makes HMR unreliable or completely non-functional for those modules (and often for the entire entrypoint).

The fix should happen inside `ModuleConcatenationPlugin`'s logic that decides which modules are safe to concatenate. If a module has any `ModuleHotAcceptDependency` or `ModuleHotDeclineDependency`, the plugin should bail out with a clear reason and exclude the module from the current concatenation attempt.

This eliminates a sharp edge where scope hoisting silently corrupts the HMR guarantees, leading to developer confusion and lost productivity.


## Bug: Malformed error messages when loaders emit or throw falsy/non-Error values

### Description

Webpack’s internal error reporting classes (`ModuleError`, `ModuleWarning`, and `ModuleBuildError`) produce poorly formatted console output when a loader emits or throws error values that are missing, `null`, or not a proper `Error` instance. In many cases the message ends with a trailing colon and no further explanation, or shows `[object Object]`, which makes debugging loader problems unnecessarily confusing.

### Steps to reproduce

1. Create a custom loader that:
   - Calls `this.emitWarning(null)` or `this.emitError(new Error())` (an `Error` without a message).
   - Throws a non-Error value, e.g., `throw "a string error"`.
2. Use that loader in a minimal webpack config.
3. Run webpack and observe the terminal output.

### Actual behavior

- Emitting `null` or an empty `Error` produces a message line like:
  `Module Warning (@ loader) :`
  (trailing colon with nothing after it, or an empty space).
- Throwing a string results in `Module build failed:` without the thrown string being shown.
- Some edge cases may print `[object Object]` instead of a useful message.

### Expected behavior

- The colon should appear **only** when there is meaningful error/warning detail to display.
- For `null` or missing details, the output should omit the colon and any dangling punctuation, keeping the message line clean.
- Non-Error thrown values (strings, numbers) should be printed as-is after the colon, preserving the information the loader intended to surface.
- Empty `Error` objects (no `message` property) should be treated like other fringe cases and not produce a “: ” gutter.

### Impact

Loader authors and users rely on webpack’s error output to diagnose build problems. The current formatting makes it hard to distinguish between a real missing message and an actual empty string message, and hides critical context when a malformed throw occurs. Fixing this improves debuggability and follows the principle of least surprise for error formatting.


When `node: false` is set in the webpack configuration, several CommonJS module expressions become unavailable even though they are not Node.js specific. The `node` option is intended to control polyfilling of Node builtins and globals (e.g., `process`, `Buffer`, `__dirname`, `__filename`, `global`, `setImmediate`). However, it currently also suppresses:

- `module`, `module.id`, `module.loaded`, `module.exports` guard
- `module.hot` evaluation
- `require.main`, `require.main.require`, `module.parent.require`

All of these are part of the CommonJS module system, not Node.js specific, and should remain functional regardless of the `node` setting. The underlying cause is that these expression handlers live inside `NodeStuffPlugin`, which is only applied when the `node` option is truthy.

We need to decouple CommonJS module system support from Node-compatibility polyfilling. Move all CommonJS-specific expression / evaluateIdentifier handlers from `NodeStuffPlugin` into a dedicated plugin that is always applied, independent of the `node` option. `NodeStuffPlugin` should continue to handle only Node.js specific features (like `process`, `Buffer`, `__dirname`, `__filename`, `global`, `setImmediate`), and its activation should still be gated by `node`.

The CommonJS handlers should be registered for the `javascript/auto` and `javascript/dynamic` parser types, matching the existing parser hooks, and produce the same behavior as when `node` is enabled—just unconditionally.


We found that webpack does not properly constant-evaluate `typeof` expressions that involve optional chaining (`?.`). For example, in production mode, `typeof someObj?.prop?.value` is left as-is in the output (including the `?.` syntax), even when `someObj`, `prop`, or the final value can be statically determined. Similarly, the result of an optional chain that is known to be `null` is not inlined (it should be replaced by `null`), and `typeof` on a chain that resolves to `null` is not constant-folded to `"object"`.

**Observed behavior**
- `typeof a?.b?.c` is not replaced with a constant string like `"number"`, `"undefined"`, or `"object"` when the chain can be fully resolved at build time.
- An optional chain expression like `a?.b?.c` that evaluates to `null` is not replaced by the literal `null` (instead the optional chaining syntax remains).
- Code guarded by these constants (e.g., `if (typeof a?.b !== "undefined")`) is not eliminated by dead-code removal, leading to larger bundles and possibly shipping `?.` syntax to environments that do not support it.

**Expected behavior**
- `typeof` on an optional chain should be constant-folded. For example:
  - If the chain always resolves to a number, the expression should be replaced by `"number"`.
  - If the chain short-circuits because a base value is known to be `null` or `undefined`, the expression should be replaced by `"undefined"`.
  - If the final result of the chain is `null`, `typeof` should evaluate to `"object"` and be inlined as such.
- The optional chain itself, when its result is statically known, should be replaced by the constant value: `undefined` when the chain short-circuits because of a nullish receiver, or the concrete value (including `null`) when the access succeeds with a known result.
- These constant-foldings must work in production mode and not be suppressed when a minimizer is present.

**Impact**
Without this constant folding, production bundles contain unnecessary optional-chaining syntax and runtime checks, increasing bundle size and potentially breaking compatibility with older browsers that do not support `?.`. Branch pruning around `typeof` guards is also missed, leaving dead code in the output.

**Additional context**
The evaluation must correctly distinguish between `null` and `undefined` because `typeof null === "object"`, while `typeof undefined === "undefined"`. When a chain like `obj?.prop` accesses a property whose value is known to be `null`, the result of the chain is `null`, so `typeof` must fold to `"object"`. Previous handling sometimes incorrectly folded all nullish outcomes to `undefined`, which would break any code that performs a strict `typeof` check for `"object"` vs `"undefined"`. The fix should also ensure that `typeof` evaluation properly recurses into `ChainExpression` AST nodes so that the hook can fire and produce the correct constant.


**Title:** Tree shaking support for destructuring patterns on imports

When a namespace or named import is destructured, webpack should treat only the actually accessed properties as “used” for tree shaking, rather than marking the entire imported binding as used.

**Observed behavior (before change):**
Any destructuring of an import causes all exports of the referenced module to be considered used, even if only a subset of properties are accessed. This prevents elimination of unused exports and increases bundle size.

**Desired behavior:**
1. **Direct destructuring from a namespace import**
   `import * as C from './module'; const { D } = C;`
   Only `D` is marked as used; other exports of `./module` (e.g., `E`, `counter`) are candidates for tree shaking if nothing else references them.

2. **Destructuring from a named import that is itself an object**
   `import { counter } from './module'; const { d } = counter;`
   Only the property `d` of the namespace represented by `counter` is marked as used. The `counter` binding itself (and any other properties of that namespace) may be tree shaken if unused elsewhere.

3. **Computed property destructuring**
   `const { ['d']: d1 } = counter;` must be recognized equivalently to static property access.

4. **No deep/nested destructuring analysis**
   `const { counter2: { d } } = C;` should **not** perform deep analysis; the intermediate key `counter2` must be considered used, ensuring that `d` alone does not become the only used export. This avoids unsafe assumptions about the shape of nested objects at compile time.

5. **Integration with existing unused-export detection**
   The tree shaking pass must reflect the narrower usage, so that `__webpack_exports_info__` (and any other instrumentation) shows the correct “used” status for the involved modules. Plugins and loaders relying on this information should see no regression—only stricter, more precise results.

**Constraints and safety:**
- The analysis must not incorrectly break re-exports or re-exported namespaces (e.g., `export { counter } from './counter'`).
- Only specifier imports (harmony) are in scope; CommonJS interop is not expected to change.
- The behavior must be backwards compatible: existing builds that do not use destructuring should see no change in output or tree shaking behavior.

This enhancement aligns with webpack’s goal of providing robust, fine-grained dead code elimination, particularly for ES module codebases that heavily use destructuring patterns.


The `AmdMainTemplatePlugin`'s hash hook currently updates the hash with `this.name` unconditionally. When `output.library` is not set (i.e., an unnamed AMD define), `this.name` is `undefined`, and `hash.update(undefined)` either inserts the string `"undefined"` or throws depending on the environment, leading to inconsistent or broken output.

Expected behavior for an unnamed AMD target:
- The generated `define()` should have no module name (anonymous).
- The hash computation should skip the name update entirely when no name is provided, avoiding any reference to `undefined`.

Guard the `hash.update(this.name)` call with a check that `this.name` is truthy. All other behavior—including the existing conditional emit of the name in the module wrapper—remains unchanged. This ensures hash stability and correct unnamed AMD output when `output.libraryTarget: "amd"` is used without `output.library`.


When building the chunk graph, the `minAvailableModules` set of a chunk group can shrink after initial processing (e.g., when a later branch reveals that some modules are not actually available in all parent paths). If child chunk groups have already been visited using the previous, larger set, they may incorrectly assume that certain modules are still available in the parent, leading to those modules being omitted from the eventual output chunks. This manifests as missing modules in chunks that share dependencies through deeply nested dynamic imports.

The chunk graph builder must track which chunk groups are children of each chunk group, and whenever a chunk group’s `minAvailableModules` shrinks, all of its already-processed children must be queued for a fresh evaluation so their own available module sets can be recomputed against the updated parent availability.


## Feature Request / Bug Report: `entry` option should accept a function (dynamic entries)

### Observed Behavior

Currently the `entry` configuration option only accepts:

- a string
- an array of strings
- an object mapping chunk names to string/array entries

If I pass a function, webpack's schema validation rejects the configuration with a validation error like:

```
configuration.entry should be one of these:
   object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]
```

There is no way to compute entry points dynamically at compilation time (e.g., based on environment, filesystem scans, or external data sources). The only workaround is to generate the configuration statically before invoking webpack, which is not always practical.

Additionally, when using array-type entries, the internal module identifier for the combined multi-module is simply `"multi <name>"` (e.g., `"multi main"`). This is not useful for debugging because it doesn't show which modules are being grouped together.

### Expected Behavior

1. **Dynamic entries via function**
   The `entry` option should also accept a **function** that returns an entry specification. The function can return:
   - A string or array (treated as the `"main"` entry)
   - An object mapping chunk names to string/array entries
   - A `Promise` that resolves to one of the above, supporting asynchronous entry discovery.

   The function is called once per compilation, and its result (or the resolved value) is used exactly like a static entry configuration. This allows patterns like:
   ```js
   entry: () => {
     return {
       app: './src/app',
       vendors: ['./src/vendor1', './src/vendor2']
     };
   }
   ```
   or with a Promise:
   ```js
   entry: () => {
     return fs.readdir('./pages').then(files => {
       const entries = {};
       files.forEach(f => { entries[f] = `./pages/${f}`; });
       return entries;
     });
   }
   ```

2. **Better multi-module identifiers**
   When multiple entry files are bundled together as a chunk, the internal `MultiModule`'s `identifier` and `readableIdentifier` should include the actual dependency requests (e.g., `"multi ./a ./b"`) instead of just a generic `"multi main"`. This makes debugging and source analysis clearer.

### Impact

Without dynamic entry support, webpack cannot be used in environments where entry points are determined at build time and depend on external factors. Users are forced to generate configuration files programmatically before each build, which complicates workflows and makes pipelines less flexible. The improved multi-module naming is a minor but helpful debugging enhancement that reduces confusion when inspecting compiled bundles or error messages.


**Title:** Entry with asset module listed before JS module fails to generate JavaScript bundle

**Description**

When an entry point includes both JavaScript and non-JavaScript asset modules (e.g., a `file.png` imported via `asset/resource`) and the asset is listed *before* the JavaScript source in the entry’s `import` array, the JavaScript output for that entry is silently dropped. The compilation completes without errors and the asset file is emitted, but the expected `.js` bundle is missing from the output.

**Steps to reproduce**

1. Configure an entry point that lists a non-JS asset first, followed by a JS entry module:

```js
entry: {
  "mixed-entry": {
    import: ["./image.png", "./app.js"]
  }
}
```

2. Ensure `./image.png` is handled by an asset module rule (e.g., `type: "asset/resource"`).
3. Run webpack.

**Observed behavior**

- No `mixed-entry.js` is emitted.
- Only the asset (image) appears among the output assets.
- No warnings or errors are reported.

**Expected behavior**

- A JavaScript bundle (`mixed-entry.js`) is emitted for the JS module.
- The asset module is emitted as a separate file, as usual.
- Entry output does not depend on the order of items in the `import` list.

**Impact**

This prevents straightforward mixed-entry configurations often used to preload assets or initialize side effects. Developers are forced to remember to put JS modules first, which is fragile and non-obvious, especially when entry configurations are generated programmatically.

**Technical context**

The issue occurs because the main entry rendering path in `JavascriptModulesPlugin` iterates over all entry modules provided by the chunk graph without checking whether each module produces JavaScript source. Non-JS asset modules (which have no “javascript” source type) should be skipped when determining which module to use for rendering the JavaScript entry bundle.


Implement a new `asset/source` module type.

When a rule has `type: "asset/source"`, the matched file should be treated as text and its raw content exposed as a string at import time.  This differs from `asset/inline` (which returns a data URL) and `asset/resource` (which emits a file and returns the public path).  No data URL encoding or file emission should occur – the module should simply export the file’s contents as a JavaScript string.

- An imported `.svg` (or any text file) must yield the exact source text (e.g. the SVG markup), not a data-URI or base64-encoded blob.
- If the file source is a Buffer, it should be decoded as UTF‑8 before export.  (Binary assets are not a primary use case, but the decoding must not throw.)
- The generated module code must be a simple `module.exports = JSON.stringify(content);`, so it works in all target environments.
- No parsing of the file’s content is performed; the parser can be the same no‑op parser used for other asset types.
- The module’s size estimate should reflect the original source size plus a small constant overhead.

This is part of the existing `experiments.asset` feature and should follow the same plugin structure (`AssetModulesPlugin`, `AssetParser`, and a new `Generator` derivative).


## Feature request: compact serialized form for small non‑negative BigInts

### Problem
When webpack’s filesystem cache serializes a `BigInt` value, even a tiny value like `0n` or `5n` is stored as the full decimal string prefixed with a length field, producing an unnecessarily large representation.  This wastes cache space and I/O bandwidth, especially since small BigInts appear frequently in configuration, metadata, and internal state.

### Desired behavior
Add a **”short BigInt” encoding** for `BigInt` values that are **between 0 and 10 inclusive**.  When such a value is encountered during serialization, the output should be:

- 1 byte header identifying the compact format
- 1 byte representing the numeric value (`0` … `10`)

All other `BigInt` values must continue to use the existing (string‑based) serialization, and deserialization must correctly distinguish between the two formats.

### Acceptance criteria
1. **Serialized size**: For any `BigInt` in `[0, 10]`, the serialized representation is exactly **2 bytes** (header + value).
2. **No false matches**: The header byte chosen for the short form does **not** collide with any existing header constant used by `BinaryMiddleware` (e.g., `I8_HEADER`, `SHORT_STRING_HEADER`, `BIGINT_HEADER`, …). If necessary, the original `BIGINT_HEADER` value may be reassigned to avoid overlap.
3. **Backward compatibility**: Deserializing a cache entry written by a previous webpack version (which only knows the full string format) must still work. Likewise, the new short form must be correctly read back by the updated code.
4. **Round‑trip correctness**:
   - Serialize then deserialize `0n`, `1n`, …, `10n` → the original value is recovered exactly.
   - Any other `BigInt` (negative, larger than `10`) survives the whole round‑trip unchanged.
5. **No side effects**: The change does not alter the serialization of any other primitive or object type; numbers, strings, buffers, arrays, etc., remain unchanged.

### Out of scope
- Optimizing small **negative** BigInts or values > 10 using a compact form (though the classification logic may be prepared for future extension).
- Changing the persistent cache format version number or migration behavior.
- Introducing runtime‑side feature flags to disable the optimization.


**Title:** `export default` with class expression incorrectly processed as a named export declaration

**Area:** `lib/Parser.js` → `walkExportDefaultDeclaration`

---

### Problem

When processing `export default` the parser must distinguish between declarations (`export default function foo() {}`, `export default class Foo {}`) and expressions (`export default (function bar() {})`, `export default (class Bar {})`). For declarations the optional `id` (`foo`, `Foo`) becomes a module-level export binding, while for expressions any `id` (`bar`, `Bar`) is scoped inside the expression and should not be treated as an export declaration.

Currently the walker already has a guard that skips further processing for function expressions:

```js
if (
	statement.declaration.id &&
	statement.declaration.type !== "FunctionExpression"
) { … }
```

This correctly prevents function expressions from entering the export-declaration branch, but the analogous check is missing for **class expressions**. Consequently `export default (class Name {})` is treated as if the class name were an export declaration, leading to incorrect scope analysis, missing renamings, or broken output.

### Desired behavior

Extend the guard so that class expressions are also excluded. The condition should become:

```js
statement.declaration.id &&
statement.declaration.type !== "FunctionExpression" &&
statement.declaration.type !== "ClassExpression"
```

After the fix, `export default (class Name {})` and `export default (function name() {})` are both treated purely as expression exports, with the inner name staying local to the function/class body.

### Constraints

- No change to handling of declaration forms (`export default function …`, `export default class …`).
- No change to unnamed expressions (where `statement.declaration.id` is `null`).
- This follows the same intent as the existing `FunctionExpression` check; parity is expected.

---

**Acceptance Criteria**

- `export default (class Name {})` does **not** trigger the `exportDeclaration` hook and does not introduce `Name` as an export binding.
- Existing behavior for function expressions and both declaration forms remains unchanged.


As a Module Federation consumer, I need to load a shared dependency at a specific semver range even when other containers already provide different versions of the same module in the same share scope. This enables gradual upgrades where two containers depend on incompatible major versions of a library without duplication.

**Acceptance Criteria**

1. **Multiple versions in the same share scope**
   When multiple containers provide the same `shareKey` (e.g., `react`) but each with a different version, all versions must be discoverable in the share scope under the same base key. The runtime must record each version distinctly so they can coexist.

2. **Version negotiation on consumption**
   When a consumer declares `requiredVersion` (e.g., `"^2"` or `">=16.8"`) for a shared module, the runtime must select the highest available version that satisfies the range. The selection must follow standard semver comparison (loose equality between number and string is acceptable as per the existing `versionToString` helpers).

3. **Strict mode enforcement**
   If the consumer specifies `strictVersion: true` and no installed version satisfies the `requiredVersion`, the runtime must throw an error synchronously, preventing the application from proceeding with an incompatible version.

4. **Non‑strict fallback behavior**
   When `strictVersion` is not set or `false`, and no version satisfying `requiredVersion` is found, the runtime must:
   - fall back to the base (unversioned) entry for that share key if it exists;
   - emit a warning (via `console.warn`) before returning the fallback entry;
   - if neither a matching version nor the base entry exists, invoke the configured `fallback` module if provided, otherwise the original behavior (likely a warning and return of `undefined` or a further fallback chain) should remain reasonable.

5. **Eager consumers must be identifiable**
   Consumers using the `eager` import mode must be treated as distinct consumption points. The resolved shared module for an eager consumer and a lazy consumer of the same version range must not be incorrectly deduplicated when the `eager` flag differs, ensuring correct module identity.

6. **Backward compatibility**
   Existing configurations that only provide or consume a single version must continue to work unchanged. That is, the absence of `requiredVersion` or the presence of only one version must still map to the base entry and not break existing behavior.

**Example scenario**
A host container provides `react@8` and `react@2.1.0` (the latter shared under a different import alias but the same `shareKey`). Another container declares:

```js
shared: {
  react: { requiredVersion: '^8', strictVersion: true },
  'old-react': {
    import: false,
    shareKey: 'react',
    requiredVersion: '^2'
  }
}
```

After federation runtime initialization, `react` resolves to the 8.x version and `old-react` resolves to 2.1.0, both available in the same share scope without collision. An upgrade of the 8.x provider to 9.x must then immediately reflect in all non‑pinned consumers while the `^2` consumer remains on 2.1.0.

allow to have multiple version in share scope


**Title:** `target: "node"` chunk loading fails when entry points reside in subdirectories (common chunks not found)

**Description:**
When using webpack with `target: "node"` and `optimization.splitChunks` to create shared chunks, if any entry point is located in a subdirectory (e.g., `inner-dir/b.js`), the generated runtime fails to load common chunks. The error manifests as a `MODULE_NOT_FOUND` error because the `require()` call emitted by the runtime uses an incorrect relative path that does not climb out of the entry’s directory.

**Steps to Reproduce:**
1. Configure webpack with multiple entry points, placing at least one in a nested directory:
   ```js
   entry: {
     a: "./a",
     "inner-dir/b": "./inner-dir/b"
   }
   ```
2. Enable chunk splitting:
   ```js
   optimization: {
     splitChunks: { chunks: "all" }
   }
   ```
3. Set `target: "node"` and `output.filename: "[name].js"`.
4. Build and run the application (or test the entry `inner-dir/b.js`). The runtime tries to load a shared chunk stored in the root output directory.

**Expected Behavior:**
The runtime should generate a correct `require()` path that resolves the shared chunk relative to the entry file. For `inner-dir/b.js`, the path for a chunk at the root (e.g., `commons.chunk.min.js`) should be `../commons.chunk.min.js` or a path based on `__dirname` that reaches the output root.

**Actual Behavior:**
The generated runtime code uses a hardcoded prefix `"./"` for the chunk filename:
```js
var chunk = require("./" + __webpack_require__.u(chunkId));
```
This resolves relative to `inner-dir/`, where `./commons.chunk.min.js` does not exist, leading to a `MODULE_NOT_FOUND` error.

**Impact:**
- Applications using the Node.js target and code splitting cannot have entry points inside nested folders; they are forced to keep all entries at the root of the output directory.
- This regression was introduced in the chunk loading runtime module (`RequireChunkLoadingRuntimeModule`) which assumes all entry points live at the bundle root.

**Desired Fix:**
The runtime should dynamically compute the correct relative directory depth from the entry file to the output root and use that as the prefix for the chunk `require()` call. For example, if the entry file is `inner-dir/b.js`, the prefix should become `"../"` (or `"../../"` for deeper nesting). When the entry is at the root the prefix should be equivalent to `"./"`. Care should be taken to use `__dirname`-based relative paths to maintain portability across operating systems, and the computation must work for any valid output filename pattern that produces nested entry paths.

Make inner folder entrypoints able to require common chunks


In `SystemMainTemplatePlugin`, the bundle wrapper code for `System.register` is assembled by hand with embedded newline and indentation strings. Replace that with `Template.indent` and `Template.asString` so the generated output is consistently indented and the plugin code is easier to maintain. The generated `System.register` wrapper must remain functionally identical; only the indentation style may change to match the project’s tab‑based conventions. Additionally, ensure the related test fixtures and test files use consistent tabs for indentation, aligning with the project’s formatting style.

Feedback from sokra. Using Template.indent and Template.asString.


**Title:** Stabilize the order of harmony export specifier dependencies

**Context:**
When multiple export specifiers appear in a single `export` statement (e.g. `export { a, b }` or `export { default as x } from './y'`), the order in which the corresponding `HarmonyExportSpecifierDependency` and `HarmonyExportImportedSpecifierDependency` instances are emitted into the generated code is currently non-deterministic. This causes the build output to change between runs, even when no source files have been modified, as described in issue #3769.

The non-determinism stems from the fact that all of these dependencies share the same source location (the whole statement), and the existing location comparison (`compareLocations`) does not differentiate between them. They are added to the dependency list without a stable secondary ordering key.

**What is needed:**
1. Each export specifier dependency must carry an additional index that reflects its **order of appearance** within the export statement.
   - For `export { a, b }`, the specifier for `a` has index 0, `b` has index 1, etc.
   - For `export { default as x } from '...'`, the re-export specifier gets the appropriate index.

2. The location comparison logic must be extended to use this index as a tiebreaker when comparing two locations that have identical line, column, and index (or the same top-level location object). This ensures that dependencies are sorted stably in source order, not only by location but also by specifier position when locations are identical.

3. Other export-related dependencies generated for the same statement (e.g., `HarmonyExportHeaderDependency`, `HarmonyImportDependency`, `HarmonyExportExpressionDependency`) must consistently appear **before** the specifiers in the dependency list. They should be assigned a negative index (e.g., `-1`) so that their relative order is fixed relative to specifier indices (which are non-negative).

4. The compatibility dependency injected by `makeHarmonyModule` should similarly receive a distinct index (e.g., `-2`) to ensure it always precedes all other export dependencies.

This will make the emitted module code fully deterministic, dependent only on the lexical order of specifiers in the source. No other sorting or behavior should change; the fix should only affect tie-breaking within identical locations.

**Affected components:**
- The `export specifier` and `export import specifier` plugin hooks need to receive and pass through the index.
- `HarmonyExportDependencyParserPlugin` must set `dep.loc.index` to the appropriate value when creating these dependencies.
- `compareLocations` (in `lib/compareLocations.js`) must compare the new index property when line/column are equal.


When a module contains an `export default` statement with comments (including `/*#__PURE__*/` annotations) between the `default` keyword and the expression, webpack’s output omits those comments. This breaks minifiers that rely on those annotations for dead-code elimination, and also causes loss of any other intentional comments.

Please ensure that all comments appearing in the source text from the beginning of the `export default` statement up to (but not including) the exported expression are preserved in the generated code. They should be placed directly before the expression in the final assignment, so that the output semantically matches the equivalent assignment `exports.default = <comments> <expression>;`.

- Comments may appear anywhere in that range (before the expression, before/after parentheses, on adjacent lines, etc.).
- Both `/* Block */` and `// Line` comments must be handled.
- The fix must not change the program’s runtime behaviour; only the presence and position of the comments in the output should change.
- The existing pure-comment optimization (e.g., `/*#__PURE__*/` causing Terser to drop the call) should now function correctly for `export default` expressions.

(Reference: issue #8039)


## Feature Request: Correct Block Scoping in Dependency Resolution

### Problem
ES6+ block‑scoped bindings (`let`, `const`, `class`) are currently hoisted to the enclosing function or module scope during webpack’s static analysis. This causes name collisions, incorrect dependency resolution, and runtime errors (e.g., `Cannot read property 'call' of undefined`). For example:

* An `import ok` at module level is overwritten by a `const ok` inside an `if` block, even after the block closes.
* `class` declarations inside plain blocks shadow external imports.
* `var` inside `for`/`for‑of`/`for‑in` loops is mistakenly treated as block‑scoped, disappearing after the loop.
* `export default (function ok() {})` leaks the inner name `ok` into the module scope, conflicting with an `import ok`.
* Catch clause parameter bindings are not properly scoped to the `catch` block.

These issues break builds that rely on correct lexical scoping and are especially noticeable when interacting with tree‑shaking and live bindings.

### Expected Behavior
The parser must respect ES6 lexical scoping rules **during the static dependency walk**:

1. **`let`, `const`, and `class` declarations inside any block (`if`, `for`, `for…of`, `for…in`, `catch`, `{}`)** are visible only within that block. The parser shall not add them to the enclosing function/module scope, and they shall not shadow or interfere with outer imports.
2. **`var` declarations** inside the same blocks remain function‑scoped (or module‑scoped) and are visible after the block.
3. **Catch clause parameters** are block‑scoped to the `catch` block.
4. **Export default declarations** (e.g., `export default function ok() {}`, `export default class {}`, `export default (function ok() {})`) must not leak the function/class name into the module scope in a way that collides with other top‑level identifiers (such as an `import ok`). They must still correctly report exported specifiers.
5. **Export specifiers** emitted during the walk should be determined without relying on the now‑removed `TrackingSet`; the new scoping mechanism should support this naturally.

### Acceptance Criteria
* A build containing an `import` of `ok` alongside a block‑scoped `const ok` inside an `if` statement resolves the import correctly after the block.
* A `class` declaration inside `{ … }` does not break an outer reference to the same name.
* `var` inside `for (var i = …)` is visible after the loop.
* `export default (function ok() {})` does not cause a conflict with `import ok from '…'`.
* Existing webpack builds relying on correct ES6 scoping continue to work without regression.

### Proposed Implementation Direction
Introduce a dedicated **block scope** concept into the parser (analogous to the existing function scope handling) that creates a child scope for definitions when entering a block. Apply this to:
* `BlockStatement` (and any statement with a block body: `if` consequent/alternate, loops, `catch`)
* Loop initializers that contain `let`/`const` declarations
* `CatchClause` parameter

Separate the pre‑walk of variable declarations into two paths:
* `var` → uses the existing `varDeclarationVar` hook and scopes to the enclosing function.
* `let`/`const`/`class` → scoped to the innermost enclosing block via `varDeclarationConst`/`varDeclarationLet`/class hooks.

Replace the `TrackingSet`‑based export default handling with a straightforward callback that emits export specifiers directly during declaration entry.

This will align the parser’s static analysis with runtime ES6 semantics and eliminate the reported scope leaks.


When `optimization.runtimeChunk` is `"single"` and multiple entry points share a runtime entry via `dependOn`, the generated runtime chunk incorrectly includes references to chunks that belong to sibling entry points (i.e., other entries that also depend on the same shared runtime). This makes the runtime chunk unnecessarily large and may cause loading of modules that are not required by the entries that actually use this runtime.

The runtime chunk should only contain the runtime logic and chunk references needed by the entry points that directly share it, not by all entry points that happen to depend on the same runtime entry. Other entry points that use `dependOn` are initial, not async, and their own subtrees (including their async imports) must not be pulled into the runtime chunk as async dependencies.

Concretely, when determining the set of async chunks for a runtime chunk, if a child chunk group is an `Entrypoint` (coming from another entry’s `dependOn`), it should not be treated as an async chunk source. Instead, only its actual async children (non-entrypoint chunk groups) should be considered, preventing the entrypoint itself and its initial chunks from being included.

fix too large runtime chunks when using dependOn


When persistent caching is enabled (for example, via `cache: { type: "filesystem" }`), certain builds that rely on module concatenation or that emit dependency-related warnings can fail with a crash after a cache hit, or silently drop warnings.

**Observed regressions:**

1. A `ConcatenatedModule` restored from cache may lack a valid `rootModule` reference at construction time. Accessing `rootModule.layer` before the module is fully wired causes a type error and crashes the build.
2. Warnings of type `ModuleDependencyWarning` and `InvalidDependenciesModuleWarning` are not correctly serialised by the caching layer. After cache deserialisation they are either missing from the module’s warning list or cause errors that prevent the build from completing normally.
3. When a module’s cached representation is used to update an existing module (e.g. via `updateCacheModule`), the `layer` property is not transferred. This can lead to incorrect behaviour when the layer matters for later processing (e.g. container hierarchy).

**Expected behaviour / invariants:**

- A build that succeeds without persistent caching must also succeed when the cache is filled and then replayed (no *new* crashes).
- All warnings that were originally emitted during a build must survive a round-trip through the cache and still be present on the affected modules.
- The `ConcatenatedModule` constructor must not assume that `rootModule` is always defined; it should safely handle the case where it receives `null`/`undefined` for that property.
- When `updateCacheModule` is called, all properties that influence runtime behaviour—including `layer`—must be copied from the cached module to the active module.

**Constraints / edge cases:**

- Do **not** change the public contracts of error/warning constructors; serialisation must be transparent to existing callers.
- The fix must not introduce new warnings or errors during normal (non-crashed) builds when caching is used.
- Any existing warnings that rely on error stack traces or other unserialisable fields should degrade gracefully after deserialisation (e.g., the error object itself may be absent, but the warning must still be present and identifiable on the module).

**Acceptance criteria:**

- Given a configuration that uses `ModuleConcatenationPlugin` and emits `ModuleDependencyWarning` or `InvalidDependenciesModuleWarning`, running a cold build (no cache) followed by a hot build (from the populated cache) must complete without crashing.
- In the hot build, the warnings list on the relevant modules must still contain those warnings (they are not lost).
- Builds that previously only emitted warnings must continue to emit the same warnings after cache replay, with no new error-level log entries appearing on stderr.


Improve error resilience in CSS modules parsing: when a `@keyframes` at-rule is malformed (e.g., terminated by a semicolon instead of a `{`), emit a warning via `_emitWarning` rather than throwing an error. The rest of the CSS should continue to parse. The warning message must include the unexpected character and its position (e.g., `Unexpected ';' at 17 during parsing of @keyframes (expected '{')`). This prevents a single broken keyframes declaration from aborting the build, which is important for production pipelines.

fix: error resistence for broken keyframes


I'm using `webpackFetchPriority` magic comments on dynamic imports to control `<script>` fetchpriority. When multiple `import()` calls target the same chunk (or share an async chunk through different chunk groups) and specify different priorities, the final priority ends up being whatever was processed last—often an unintended lower priority—instead of respecting the first load.

**Steps to reproduce:**
1. Have two dynamic imports that eventually load the same chunk, e.g.
   `import(/* webpackFetchPriority: "high" */ "./shared")` and
   `import(/* webpackFetchPriority: "low" */ "./shared")`.
2. Observe the emitted script tag's `fetchpriority` attribute.

**Actual behavior:**
Depending on import order, the chunk may get `low` priority even though a `high` priority import exists. The priority can be overwritten by a later import with a different (or missing) explicit priority, especially when a chunk group’s default `fetchPriority` is applied.

**Expected behavior:**
The first explicitly assigned fetch priority (or the first effective group priority) for a given chunk should be stable and not replaced by subsequent imports. If a chunk is already assigned a priority, later conflicting imports must not change it.

**Impact:**
This breaks deterministic priority assignment and can lead to suboptimal loading performance (e.g., critical chunks loading with low priority while less important ones override them).

The issue appears in `ChunkPrefetchPreloadPlugin` where the chunk-id → fetchPriority map is built; it currently allows later values to clobber earlier ones. The fix would only set the priority when no value has been set yet, preserving the first decision.