v1.10.0 is a correctness release: 95 fixes, no new bundler formats. Most of the work went into two areas β SystemJS modules now decompile to real ESM exports in many more shapes, and CommonJS .default interop is recovered behind cross-module proofs that fail closed. Also new: wakaru debug validate reports source locations and flags CommonJS residuals.
π SystemJS exports, reconstructed
- Exports written through
_exportin assignment,var-initializer, sequence, and expression forms are reconstructed into ESM export declarations instead of surviving as runtime calls. - Setter re-exports are recovered: live setter re-exports no longer synthesize fake locals, arbitrary and named-object setter re-export shapes are reconstructed, and re-export names are preserved exactly.
System.registermodules whosedeclaretakes no export parameter are reconstructed; unreadabledeclareparameters fail closed instead of guessing.- Every export emission path now proves the target name is free before binding an export directly; unrepresentable export names take the shared alias path, and function-callee IIFEs are parenthesized on every emit path.
- Export sequence semantics, default-export expression context, chained exports (which now reuse live bindings), and IIFE exports preceding member assignments are all preserved.
ποΈ CommonJS interop, proven then recovered
- Default-only providers, coupled lazy defaults, and exact ordered
Object.assigncopy shells are proven at the multi-module fact barrier and recovered β mixed surfaces, unresolved providers, extra runtime behavior, and cycles fail closed. - Proven CommonJS self reads, property imports, object imports, callable property imports, and named-only provider imports are repaired into direct ESM references.
- CommonJS export-star loops are recovered, defaults are recovered from export getter maps, and default-compat postambles are matched in logical form and dropped when proven dead.
- The proofs fail closed on direct
evalreads, compound writes and optional chains, prototype-mutating members (__proto__,__defineGetter__,__defineSetter__), conditional callable exports, residual requires, and mid-body directives βexports.__proto__ = valuestays an honest residual instead of becoming a fabricated named export. - Webpack inner-UMD wrappers: proven defaults are recovered, inner exports must be unconditional, and deferred rewrites are rejected.
π New recovery
- Minified TypeScript CJS enums: the collapsed
(exports.X || (exports.X = {}))enum IIFE is proven literal-only and recovered as an exported enum object β with the reserved-name, deferred-read,eval, and binding-grammar holes closed and each rejected shape covered by tests. - Called module-export assignments are lowered through receiver chains, chained local default exports are split, and default exports are recovered from
varinitializers.
π§ Validation & diagnostics
wakaru debug validatefindings now carry source locations βfilename:line:columnin human output, one-basedline/columnfields in--json.- The validator reports CommonJS residuals: unresolved
module/exportsruntime uses left in files that contain ESM syntax (direct safetypeofprobes excluded). - Import-backed local re-exports resolve to their origin, ambiguous star exports are detected, duplicate export declarations are pinpointed, reported import cycles carry a real cycle witness, and repeated parser recovery warnings are coalesced.
- With
--unpack=inspectand--provenance, fine modules split from one oversized write component carry optionalcontext_rangesidentifying the coarse evidence-pooling context in the original input.
π¦ Webpack
- CSS runtime modules: runtime metadata is recovered and emitted CSS adapter forms are handled.
- Reused loader and runtime parameters are localized per factory, unsafe loader reuse is isolated, and reuse normalization is gated by alias lifetime.
- String module IDs now emit JavaScript filenames: non-JS resource IDs append
.js(src/style.lessβsrc/style.less.js), loader queries and URL fragments are stripped from filesystem names, and collisions get stable suffixes. - Identity substitution requires a stable module surface, the guarded global fallback is hardened, generated global injection is recovered, empty-factory default exports are restored, and wrapper lifting respects class execution contexts.
π‘οΈ Rename & binding safety
- A capture sweep across the rename rules: parameter defaults, named exports, alias recovery, value renames, and namespace aliases can no longer be captured by inner scopes or globals, and parameter-default binding order is preserved.
- The shared rename shadow index now fails closed (and trips a debug assertion) when queried about a binding it never analyzed, and JSX intrinsic-tag checks use ASCII lowercase β matching the
/^[a-z]/test JSX transforms actually apply. - Object-rest synthetic aliases are sanitized for string keys and made collision-free; mutable require locals stay mutable;
constis recovered after declaration merges; externally usedfor...ofloop bindings survive.
βοΈ Async, accessors, generators
- Async flattening preserves callable names and renames colliding bindings instead of capturing them.
- Class accessor recovery is verified before conversion, and legacy TypeScript accessor forms are preserved.
- TypeScript async state machines and regenerator decoding preserve state-callback locals.
Full changelog: v1.9.0...v1.10.0