Turbopack: scope hoisting (#79459)
Enable Turbopack to merge modules together (when possible), getting rid of the `"module id...": (__turbopack_context__) => { ... __turbopack_esm_export__({foo: () => foo})` overhead:
<img width="1591" alt="Bildschirmfoto 2025-06-14 um 14 13 36" src="https://github.com/user-attachments/assets/b6baccbe-a2c7-4acd-b17b-f7bd91c8f349" />
## Details
There is a lot of complexity here, mostly for the problem of when this is actually safe to do.
Generally, modules can only be merged if they are known to always execute in that exact order (also meaning in every chunk these modules are part of).
This is done by first propagating a bitmap on the whole module graph, to determine which modules are safe to merge together (module type is compatible, only ESM, etc). Then, these potential merged groups are linearized in execution order _per chunk_. These orderings are then split up until every module is just part of a single ordering (together with the modules that are always executed before/after it, if any). Each of these orderings then becomes a merged module.
This information is then used to replace these modules with the merged version in the middle of chunking (after the module graph -> vec of modules step, but before turning vec of modules -> vec of chunks).
For code generation, the runtime helpers are omitted and imports just become straight variable references (i.e. across modules). This (together with preventing local variable naming collisions in the merged module) is achieved by leveraging swc's syntax contexts (each module effectively gets it's own syntax context, so that variables of the same name don't collide, and then imports are rewritten to point to the local variable in the other module). Comments and source maps work by encoding the module into the `BytePos`, so that a given `BytePos` in the merged AST can be decoded back into the module that it originated from, to lookup comments and source locations in the right structs.