Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

`$safeNavigationMigration(...)` in an event listener reads template locals from the wrong context

Cerrado
#585 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Ya se ha fusionado un pull request relacionado.

  • #587 de @edbzn — fusionado

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
55/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
rust

Línea de trabajo

Start by reading remove_safe_navigation_migration and the name resolution phase that handles listener handlerOps; the issue identifies both as possible points where the local scope is lost. Compare listener compilation with the working property binding in a focused reproduction using the supplied template. Done when the listener reads the restored option_r2 value and a regression test covers template locals inside migrated listener expressions.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Summary

When $safeNavigationMigration(expr) is used inside an event binding, OXC resolves template-local
variables in expr (@for items, @if … as x aliases, let- variables) against the listener's
ctx (ctx.option) instead of the local restored from the view (option_r2). The argument is
always undefined, so the expression evaluates to null.

Property bindings that use the same builtin compile correctly. The bug is specific to listener
handler ops.

Reproduction (@oxc-angular/[email protected], @oxc-angular/vite/api)

import { transformAngularFile } from '@oxc-angular/vite/api';

const src = `import { Component } from '@angular/core';
@Component({ selector: 'x-probe', template: \`
@for (option of options; track $index) {
  <button (click)="pick(option?.value); pick2($safeNavigationMigration(option?.value))"
          [title]="$safeNavigationMigration(option?.label)"></button>
}\` })
export class Probe { options: any[] = []; pick(v: any) {} pick2(v: any) {} }`;

const r = await transformAngularFile(src, '/tmp/probe.component.ts', {}, { templates: {}, styles: {} });
console.log(r.code);
Actual
i0.ɵɵlistener("click", function Probe_For_1_Template_button_click_0_listener() {
  const option_r2 = i0.ɵɵrestoreView(_r1).$implicit;
  const ctx_r2 = i0.ɵɵnextContext();
  ctx_r2.pick(((option_r2 == null) ? null : option_r2.value));          // correct
  return i0.ɵɵresetView(ctx_r2.pick2(((ctx.option == null) ? null : ctx.option.value))); // wrong: ctx.option
});
// update block, correct:
i0.ɵɵproperty("title", ((option_r3 == null) ? null : option_r3.label));
Expected (what ngc emits)

The listener should read option_r2 for both calls:
ctx_r2.pick2(((option_r2 == null) ? null : option_r2.value)).

Impact

Angular's ng update migration for the v22 safe-navigation change inserts $safeNavigationMigration
automatically. Any migrated listener such as (click)="select($safeNavigationMigration(item?.id))"
inside @for/@if as/*ngFor now passes null at runtime. There's no compile error. In our
monorepo this broke a shared select component (every dropdown emitted null) and profile
activation toggles, and failed 21 component tests across 4 projects that pass under
@analogjs/vite-plugin-angular / ngc. Rewriting the three affected bindings as x?.y ?? null
made all 21 pass under OXC.

Possible cause

remove_safe_navigation_migration iterates view.create and view.update. Angular's
unit.ops() also yields each listener's handlerOps. If the marker in handler ops isn't converted
before resolve_names, or is converted with a different scope, the argument's LexicalReads skip
the restored-view locals. Unverified, this is a guess from reading the phase source.

Environment

  • @oxc-angular/vite 0.0.41 (linux-x64-gnu binding)
  • Angular 22.2.0, Vite 7.3.6
Lenguaje dominante
Rust
Estrellas
240
Forks
24
Merge medio
1 d 15 h
PR fusionados (30 d)
75

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de voidzero-dev/oxc-angular-compiler

Todos los issues de voidzero-dev/oxc-angular-compiler

Issues similares

Más issues de Rust

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.