MODULO 4.1

🖥️ Ink Renderer

O pipeline de renderizacao de 7 estagios do Ink que converte arvores de componentes React em saida de terminal com performance de microsegundos e zero pressao de garbage collection.

7
Estagios
~60
Minutos
Deep
Nivel
Source
Tipo
1

🎯 Stage 1 -- React Reconciler

Um react-reconciler customizado conecta o React ao DOM proprio do Ink, em vez do browser. Quando <Text> esta aninhado dentro de outro <Text>, o no interno se torna ink-virtual-text -- um no fantasma sem backing do Yoga.

Event Handlers

Event handlers sao armazenados separadamente em node._eventHandlers, prevenindo repinturas desnecessarias quando componentes pais re-renderizam com novas referencias de callback.

2

🌳 Stage 2 -- Virtual DOM

Arvore de objetos TypeScript simples com nos DOMElement. O dirty flag sinaliza se re-renderizacao e necessaria -- nos inalterados sao copiados do frame anterior, entregando performance O(celulas alteradas).

Tipos de Nos

ink-root ink-box ink-text ink-virtual-text ink-raw-ansi ink-link ink-progress
3

📐 Stage 3 -- Yoga Layout

Yoga e um engine de Flexbox em C++ compilado para WebAssembly. A interface LayoutNode desacopla o codebase dos bindings WebAssembly do Yoga.

⚠️ Detalhe Critico

Como ink-virtual-text, ink-link e ink-progress nao possuem nos Yoga, DOM index != yoga index. Contagem manual de siblings precedentes com nos Yoga e necessaria.

4

🎨 Stage 4 -- renderNodeToOutput

Caminhada recursiva pela arvore convertendo nos com layout em operacoes de Output. O Blit Fast Path verifica: se o no esta limpo, posicao inalterada e prevScreen disponivel, emite uma unica chamada output.blit().

📊 ScrollBox Hardware Scroll

Emite sequencia DECSTBM + SU/SD para frames de scroll em O(1), aproveitando regioes de scroll do terminal em vez de repintar todo o conteudo.

5

📦 Stages 5-6 -- Output Queue & Screen Buffer

O Stage 5 e uma abstracao de command-buffer coletando operacoes: write, blit, clear, clip/unclip, shift, noSelect. Replay em dois passes: Pass 1 expande a bounding box de dano, Pass 2 executa operacoes.

Packed Int32Array -- Screen Buffer

2 words por celula (8 bytes total), eliminando alocacao per-cell de objetos:

Word Conteudo Bits
word0 charId 32 bits
word1 styleId [31:17] + hyperlinkId [16:2] + width [1:0] 32 bits

💡 Por que Int32Array?

Um terminal 200x120 alocaria 24.000 objetos por frame. Com Int32Array, zero pressao de GC. O StylePool faz intern, transition e cache. transition(fromId, toId) pre-computa strings de escape ANSI.

6

⚡ Stage 7 -- Cell Diff & Wide Characters

O diff caminha apenas pela damage bounding box. Para cada celula alterada, emite sequencia ANSI minima.

CellWidth Enum

Narrow
1 coluna
Wide
2 colunas
SpacerTail
Segunda metade
SpacerHead
Primeira metade
7

🗺️ Pipeline Completo de Renderizacao

flowchart LR
    A["Stage 1\nReact Reconciler\nreconciler.ts"] --> B["Stage 2\nVirtual DOM\ndom.ts"]
    B --> C["Stage 3\nYoga Layout\nlayout/"]
    C --> D["Stage 4\nrenderNodeToOutput\nrender-node-to-output.ts"]
    D --> E["Stage 5\nOutput Queue\noutput.ts"]
    E --> F["Stage 6\nScreen Buffer\nscreen.ts\nPacked Int32Array"]
    F --> G["Stage 7\nCell Diff\nMinimal ANSI"]
                    

📋 Resumo do Modulo

O dirty flag e a otimizacao central -- frames em steady-state tocam apenas O(celulas alteradas)
Yoga e um engine Flexbox em WebAssembly -- mesmo algoritmo de layout do React Native
O screen buffer usa typed array (2 Int32s por celula), nao objetos -- elimina pressao de GC
A classe Output e um command buffer com design de dois passes para interacao correta de clip/damage
Alt-screen mode tem tres invariantes interligados: altura limitada, viewport falso, cursor limitado
O reconciler evita marcar dirty para event handlers
O charCache no Output e o acelerador de hot path do tokenizer -- maioria das linhas nao muda entre frames
Voltar para Trilha Proximo Modulo