Renders a linked module graph into one classic script.
The output shape, and why
One outer IIFE. Inside it, each module is an inner IIFE assigned to a var,
emitted in dependency order:
(function () {
'use strict';
var __avx3 = (function () { var __x = {}; ...body...; return __x; })();
var __avx7 = (function () { var { thing } = __avx3; ...body...; })();
})();
var rather than const is load-bearing: var hoists to the top of the
outer function, so a module emitted before its dependency — which happens
exactly once per cycle — can still name it. The binding is undefined at
that moment and holds the exports object by the time anything dereferences
it, which is the same shape the language itself has across a cycle.
Three problems this file has to get right
Live bindings. reactive/watcher.js has export let activeWatcher, it
reassigns it, and runtime/AvenxComponent.js reads it across the module
boundary to decide whether it is inside its own render. Copying the value at
import time would capture null forever and break that check silently. So a
mutable exported binding is hoisted out of its module into bundle scope
under its own name: the exporter's assignments and every importer's reads
then resolve to one variable through the ordinary scope chain, with no
identifier rewriting anywhere. Exports are exposed as getters for the same
reason, so a namespace or a re-export barrel sees the current value.
Cycles. Across the one edge that closes a cycle, the dependency's exports object does not exist yet. ES modules make exactly one guarantee there — function declarations hoist — so this emitter reproduces exactly that: a cyclic import of a function becomes a forwarder that dereferences on call, and a cyclic import of anything else is a build error, because in a browser it would be a temporal dead zone.
Line fidelity. Every rewritten declaration is emitted on a single line and padded back to the line count it replaced, so a module's body keeps a 1:1 line correspondence with its source. That is what makes the source map exact and a production stack trace point at a line the developer wrote.
- Source:
Classes
Members
(inner, constant) PRELUDE :string
The prelude every bundle carries.
One helper, five lines. A module system that needs more machinery than this at runtime has moved work out of the build that belonged in it.
Type:
- string
- Source:
Methods
(static) emitBundle(options) → {Object}
Renders a linked graph into a single classic script.
Parameters:
- Source:
Throws:
-
When the graph cannot be rendered correctly.
- Type
- EmitError
Returns:
The bundle.
- Type
- Object
(static) mutableExports(module) → {Set:.<string:>}
Finds the exported bindings a module can reassign.
Only let and var declarations qualify. A const, a function and a
class binding cannot be reassigned, so copying their value at import time
is indistinguishable from a live binding and costs nothing.
Parameters:
| Name | Type | Description |
|---|---|---|
module |
object | A graph module. |
- Source:
Returns:
Names that must live at bundle scope.
(inner) buildSourceMap(options) → {object}
Builds a line-level source map for an emitted bundle.
Line-level rather than column-level, and exact rather than approximate: every rewritten declaration was padded back to the line count it replaced, so output line N of a module's body is source line N of that module. A stack trace from a production bundle therefore names a file and a line the developer wrote.
Parameters:
| Name | Type | Description | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
options |
object | Map options. Properties
|
- Source:
Returns:
A source map, version 3.
- Type
- object
(inner) cyclicBinding(local, imported, target, importer, slotFor) → {string}
Builds a binding for an import that crosses a cycle.
The dependency's exports object does not exist yet at this point — the importing module is running inside the call that will produce it — so the forwarder cannot go through it. It goes through a bundle-scope slot instead, which the exporting module fills from its hoisted function declaration before its own body runs. That is exactly the order ES modules use, so a cyclic call that works in a browser works here and one that does not, does not.
Parameters:
| Name | Type | Description |
|---|---|---|
local |
string | The local name to declare. |
imported |
string | The name being imported. |
target |
object | The exporting graph module. |
importer |
object | The importing graph module. |
slotFor |
function | Allocates the shared slot. |
- Source:
Throws:
-
When the binding cannot legally cross a cycle.
- Type
- EmitError
Returns:
The declaration.
- Type
- string
(inner) functionExportLocal(module, exported) → {string|null}
The local name under which a module declares an exported function.
This is the question that decides whether a cyclic import is legal, so it is answered from the declaration rather than guessed from usage: only a function declaration is initialised before any module body runs, which is the one guarantee ES modules make across a cycle.
Parameters:
| Name | Type | Description |
|---|---|---|
module |
object | The exporting graph module. |
exported |
string | The exported name. |
- Source:
Returns:
The local declaration name, or null when the export is not a function declaration.
- Type
- string | null
(inner) lineCount(text) → {number}
Counts the lines a chunk of text occupies.
Parameters:
| Name | Type | Description |
|---|---|---|
text |
string | The text. |
- Source:
Returns:
Line count, minimum one.
- Type
- number
(inner) moduleBinding(index) → {string}
A valid JavaScript identifier for a module's exports object.
Parameters:
| Name | Type | Description |
|---|---|---|
index |
number | The module's index in emission order. |
- Source:
Returns:
The binding name.
- Type
- string
(inner) padToLines(generated, original) → {string}
Pads generated text so it occupies the same number of lines it replaced.
Parameters:
| Name | Type | Description |
|---|---|---|
generated |
string | Replacement text, expected to be one line. |
original |
string | The text being replaced. |
- Source:
Returns:
The replacement, newline-padded.
- Type
- string
(inner) renderCjsBody(context) → {string}
Wraps a CommonJS module so the bundle can evaluate it.
Parameters:
| Name | Type | Description | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
context |
object | Emission context. Properties
|
- Source:
Returns:
The wrapped body.
- Type
- string
(inner) renderEsmBody(context) → {string}
Renders one module's body with its declarations rewritten.
Parameters:
| Name | Type | Description | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
context |
object | Emission context. Properties
|
- Source:
Throws:
-
When a construct cannot be rendered correctly.
- Type
- EmitError
Returns:
The transformed module body.
- Type
- string