Module: lib/compiler/ir/nodes

The template intermediate representation, and the vocabulary the front and back halves of the compiler agree on.

Why an IR exists

Avenx used to compile a template by rewriting it into different markup. <@for item in items> became <template data-ax-for="items" data-ax-as="item">, <@suspense> became <div data-ax-suspense>, and the runtime rediscovered what each of them meant by reading those attributes back off the live DOM with querySelectorAll.

That is a compiler that throws its own analysis away. Every consequence followed from it: the render-program backend could not compile a list, because by the time it ran the list was an anonymous <template> element carrying strings; the runtime had to ship a second renderer to interpret those attributes; and a > inside a header expression broke the rewrite because a regex was the only thing left that could read it.

The IR is where a construct's meaning is written down instead. A <@for> becomes a ForNode with a list expression, a binding name, an optional key and two child fragments. Nothing downstream has to guess, and nothing has to parse markup a second time.

The shape, and why fragments are explicit

A FragmentNode is a compile boundary: each one becomes its own skeleton and its own op list in the emitted program, and its own DOM range at run time. Control flow owns fragments rather than containing raw children, because "the body of this loop" is exactly the unit that gets cloned per item and torn down per removal. Making that unit implicit is how a list renderer ends up re-deriving its own boundaries.

Extension

Adding a construct means adding a kind here, a builder case in module:lib/compiler/ir/build, and a lowering case in module:lib/compiler/ir/lower. A construct with no lowering case is refused with its own reason rather than silently mis-emitted, which is the same compile-or-refuse rule the render program has always followed -- moved one layer earlier, where the reason is still specific enough to be useful.

Source:

Classes

IRRefusal

Members

(static, constant) BindingKind :string

Kinds of value binding an element can carry.

Type:
  • string
Source:

(static, constant) IRKind :string

IR node kinds.

Type:
  • string
Source:

(static, constant) RefusalReason :string

Why a template, or part of one, could not be represented in the IR.

These are the constructs the IR does not model yet. They are enumerated rather than free text so a build can group them, and so a reader can tell "not implemented" from "gave up".

Type:
  • string
Source:

Methods

(static) comment(value) → {object}

Creates a comment node.

Parameters:
Name Type Description
value string

The comment body.

Source:
Returns:

The comment node.

Type
object

(static) component(name, optionsopt) → {object}

Creates a child-component node.

Parameters:
Name Type Attributes Description
name string

The component's registered PascalCase name.

options object <optional>

Component parts.

Properties
Name Type Attributes Description
props Array:.<object:> <optional>

Static and bound props.

children Array:.<object:> <optional>

Transcluded content.

Source:
Returns:

The component node.

Type
object

(static) conditional(branches) → {object}

Creates a conditional node.

Branches are ordered and the first whose test is truthy renders. A branch with a null test is the <@else> and may only appear last; the builder enforces that, so nothing downstream has to re-check it.

Parameters:
Name Type Description
branches Array:.<{test:: (string:|null:), body:: object:}>

Ordered branches.

Source:
Returns:

The conditional node.

Type
object

(static) deferred(when, body, placeholderopt) → {object}

Creates a deferred block.

Parameters:
Name Type Attributes Description
when string

The trigger: idle, visible, hover, click, interaction, a duration such as 2s, or an expression.

body object

The fragment rendered once the trigger fires.

placeholder object | null <optional>

The fragment rendered until it does.

Source:
Returns:

The defer node.

Type
object

(static) element(tag, optionsopt) → {object}

Creates an element node.

Parameters:
Name Type Attributes Description
tag string

The tag name.

options object <optional>

Element parts.

Properties
Name Type Attributes Description
attrs Object:.<string:, string:> <optional>

Static attributes.

bindings Array:.<object:> <optional>

Value bindings.

events Array:.<object:> <optional>

Event bindings.

children Array:.<object:> <optional>

Child nodes.

selfClosing boolean <optional>

Whether the tag is void or self-closed.

isStatic boolean <optional>

Whether the subtree provably never changes.

Source:
Returns:

The element node.

Type
object

(static) fragment(childrenopt) → {object}

Creates a fragment.

Parameters:
Name Type Attributes Description
children Array:.<object:> <optional>

Child IR nodes.

Source:
Returns:

The fragment node.

Type
object

(static) interpolation(expr, rawopt) → {object}

Creates an interpolation node.

Parameters:
Name Type Attributes Description
expr string

The expression source.

raw boolean <optional>

True for {{{ }}}, which inserts markup.

Source:
Returns:

The interpolation node.

Type
object

(static) isBlockNode(node) → {boolean}

Whether a node introduces its own compile and DOM boundary.

Control flow does; an element does not. Used by the lowering pass to decide where one skeleton ends and the next begins.

Parameters:
Name Type Description
node object

An IR node.

Source:
Returns:

True when the node owns fragments.

Type
boolean

(static) iteration(parts) → {object}

Creates an iteration node.

Exactly one of item and destructure is set: the first for x in xs, the second for [a, b] in pairs, which destructures each element rather than binding an index. The index is bound implicitly under the name index by the runtime and is therefore not part of the node.

Parameters:
Name Type Description
parts object

Loop parts.

Properties
Name Type Description
list string

The list expression source.

item string | null

The name bound to each element.

destructure Array:.<string:> | null

Names each element is destructured into.

key string | null

The key expression source, when declared.

body object

The per-item fragment.

empty object | null

The fragment rendered for an empty list.

Source:
Returns:

The iteration node.

Type
object

(static) slot(name, fallbackFragmentopt) → {object}

Creates a slot outlet.

Parameters:
Name Type Attributes Description
name string

The slot name; default when unnamed.

fallbackFragment object <optional>

Content rendered when nothing is transcluded.

Source:
Returns:

The slot node.

Type
object

(static) text(value) → {object}

Creates a literal text node.

Parameters:
Name Type Description
value string

The character data.

Source:
Returns:

The text node.

Type
object

(static) walkIR(node, visit, parentopt)

Walks every node in an IR tree, depth first, including fragment bodies.

Parameters:
Name Type Attributes Description
node object

The root node.

visit function

Called with each node and its parent.

parent object | null <optional>

The parent, for recursive calls.

Source: