Skip to content

fix(migrate): codemod ctx não reescreve mais dentro de strings e comentários - #511

Open
JonasJesus42 wants to merge 1 commit into
mainfrom
fix/ctx-compat-string-guard
Open

fix(migrate): codemod ctx não reescreve mais dentro de strings e comentários#511
JonasJesus42 wants to merge 1 commit into
mainfrom
fix/ctx-compat-string-guard

Conversation

@JonasJesus42

@JonasJesus42 JonasJesus42 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Contexto

O codemod transformCtxCompat (migração Fresh → TanStack) transforma leituras de ctx em optional chains
para que uma app não configurada no site alvo devolva undefined em vez de lançar — sem isso o
withSectionLoader engole a exceção e a seção renderiza em branco.

Ele varre o arquivo caractere a caractere, sem nenhuma noção de fronteira de string ou comentário. O
resultado é que um ctx. que aparece como texto era reescrito igual a um que aparece como código:

console.log('ctx.device:', ctx.device);
// vira
console.log('ctx?.device:', ctx?.device);

A chamada é corrigida certo e a mensagem ao lado é corrompida em silêncio. E compila, então nada pega —
nem build, nem typecheck, nem teste. Vale igual para strings com aspas duplas, comentários de linha e de
bloco, e o texto de template literals.

Nenhum teste cobria isso.

O que muda

Um guard de literal/comentário no laço de varredura. Ao encontrar //, /* */, '…' ou "…", o trecho é
copiado verbatim em vez de escaneado.

Template literals não são pulados por inteiro, porque suas interpolações são código de verdade. São
rastreados com uma pequena pilha de contexto, de modo que:

`${ctx.vtex.account}`      `${ctx?.vtex?.account}`   // código: reescreve
`ctx.device`               `ctx.device`              // texto: preserva

Isso também cobre template aninhado (`a${`b${ctx.device}`}c`) e aspas escapadas dentro de string.

Regex literais ficam deliberadamente de fora, e o motivo está num comentário no código: distinguir /re/
de uma divisão exige parsing de verdade, e errar o palpite faria o scanner consumir código vivo. Um ctx.
dentro de uma regex num loader é raríssimo perto desse risco.

Por que não ts-morph

O blocks-cli já depende de ts-morph, e reescrever por AST eliminaria a classe inteira de bug em vez de
tratar os casos que a gente lembrou. Não fiz isso aqui porque o scanner carrega lógica já testada e sutil
(isAssignTarget, chains já opcionais, acesso computado balanceado), e a reescrita traria risco de regressão
desproporcional ao bug. Fica como um caminho conhecido caso o scanner precise crescer de novo.

Validação

Cinco testes de regressão. Quatro deles falham contra a implementação anterior — verifiquei revertendo o
source e rodando a suíte, para o teste não ser decorativo:

× does not rewrite ctx inside string literals
× does not rewrite ctx inside double-quoted strings or escaped quotes
× does not rewrite ctx inside comments
× does not rewrite template text but DOES rewrite ${} interpolation

13 testes no arquivo (8 existentes + 5 novos), todos passando. Suíte completa em 2589 passando; as 4
falhas em draft preview são pré-existentes no main. Lint e typecheck limpos.

Procedência

Encontrado por um /code-review que se anunciava como sendo do #510. Não é: o #510 tem 16 arquivos e nenhum
deles é ctx-compat.ts (conferido pela API do GitHub). O review provavelmente rodou sobre o diff local de
outro workspace. O bug, porém, é real e independente de qualquer PR — daí este ir separado.

🤖 Generated with Claude Code


Summary by cubic

Corrige o codemod transformCtxCompat para não reescrever ctx. dentro de strings, comentários e texto de template literals. Antes, console.log('ctx.device:', ctx.device) virava console.log('ctx?.device:', ctx?.device), corrompendo mensagens em silêncio sem quebrar compilação.

O que mudou

  • Adiciona guard de literais e comentários no laço de varredura.
  • Template literals são rastreados com pilha: reescreve apenas interpolações ${}.
  • Regex literals ficam de fora deliberadamente por risco de parse incorreto.
  • Adiciona cinco testes de regressão; quatro falham na implementação anterior.

Written for commit 1a25167. Summary will update on new commits.

Review in cubic

…comments

`transformCtxCompat` walks the file character by character with no notion of
string or comment boundaries, so a `ctx.` occurring as *text* was rewritten the
same as one occurring as code:

    console.log('ctx.device:', ctx.device);
 -> console.log('ctx?.device:', ctx?.device);

The call site is patched correctly and the message next to it is silently
corrupted — it still compiles, so nothing catches it. Same for double-quoted
strings, line and block comments, and template literal text.

Adds a literal/comment guard to the scan loop. Template literals are tracked
with a small context stack rather than skipped wholesale, because their `${}`
interpolations ARE code: `` `${ctx.vtex.account}` `` must still be rewritten
while `` `ctx.device` `` must not.

Regex literals are deliberately left untracked, and the reason is in a comment:
telling `/re/` from division requires real parsing, and guessing wrong would
consume live code. A `ctx.` inside a regex in a loader is vanishingly rare next
to that risk.

Five regression tests, four of which fail against the previous implementation
(verified by reverting the source and re-running).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@JonasJesus42
JonasJesus42 requested a review from a team August 27, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant