Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

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

已關閉
#585 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

已經有一個關聯 PR 被合併了。

  • #587 來自 @edbzn —— 已合併

評估

難度
4/5
預估耗時
3-5 天
新手友好度
55/100
Issue 類型
缺陷
描述清晰度
基本清楚
活躍度
活躍
技術堆疊
rust
領域
backend, compilers

研究方向

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.

由索引模型根據 Issue 內容生成。

描述

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
主要語言
Rust
星號
240
分支
24
平均合併
1 天 15 小時
30 天內合併 PR
75

環境準備

這個專案沒有提供開發容器、Dockerfile 或貢獻指南,環境需要你自己搭建:先看它的 README,通用步驟見我們的新手貢獻指南。

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

voidzero-dev/oxc-angular-compiler 的其他 Issue

查看 voidzero-dev/oxc-angular-compiler 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。