ResizeObserverエラーを回避する循環参照の防止

shoelace-style/webawesome

Chromiumベースのブラウザで <wa-split-panel> のサイズ変更時に発生していた ResizeObserver エラーが修正されました。この問題は、positionpositionInPixels の相互監視による循環参照が原因で、プロパティ変更の条件チェックを追加することで解決されています。

背景

<wa-split-panel> コンポーネントで primary 属性を設定し、プライマリではないパネルが縮小されると、ChromiumベースのブラウザでResizeObserverエラーが発生していました。#2018 で報告されたこの問題は、ブラウザウィンドウを狭めて非プライマリパネルのコンテンツが圧縮される状態で再現します。

再現時には「ResizeObserver loop completed with undelivered notifications」という警告がコンソールに出力されていました。この警告は、ResizeObserverのコールバック内で要素のサイズを変更し、それが次の監視サイクルをトリガーする循環が発生していることを示しています。

技術的な変更

split-panel.tshandleSizeChangehandlePositionChangehandlePositionInPixelsChange の3つのウォッチャーに条件チェックが追加されました。

handleSizeChangeの変更

変更前:

if (this.primary) {
  this.position = this.pixelsToPercentage(this.cachedPositionInPixels);
}

変更後:

if (this.primary) {
  const newPosition = this.pixelsToPercentage(this.cachedPositionInPixels);
  if (this.position !== newPosition) {
    this.position = newPosition;
  }
}

handlePositionChangeの変更

変更前:

this.cachedPositionInPixels = this.percentageToPixels(this.position);
this.positionInPixels = this.percentageToPixels(this.position);

変更後:

this.cachedPositionInPixels = this.percentageToPixels(this.position);

const newPositionInPixels = this.percentageToPixels(this.position);
if (this.positionInPixels !== newPositionInPixels) {
  this.positionInPixels = newPositionInPixels;
}

handlePositionInPixelsChangeの変更

変更前:

this.position = this.pixelsToPercentage(this.positionInPixels);

変更後:

const newPosition = this.pixelsToPercentage(this.positionInPixels);
if (this.position !== newPosition) {
  this.position = newPosition;
}

すべてのウォッチャーで 値の更新前に実際に変更が必要かを確認 するパターンが適用されています。この変更により、パーセンテージとピクセル値の相互変換時に丸め誤差などで値が変わらない場合、不要な更新がスキップされます。

ドキュメントの更新

ドキュメントの変更では、<wa-select>value="" を削除し、代わりに <wa-option value="">selected 属性を追加することで、デフォルト選択状態を明示的にしています。

変更前:

<wa-select label="Primary Panel" value="" style="max-width: 200px; margin-top: 1rem;">
  <wa-option value="">None</wa-option>

変更後:

<wa-select label="Primary Panel" style="max-width: 200px; margin-top: 1rem;">
  <wa-option value="" selected>None</wa-option>

これにより、デモページの初期状態がより明確になります。

設計判断

プロパティ更新の条件チェックによる循環参照の遮断 という手法が採用されました。

コード内のコメントでは、この修正が「circular watch loop」を防ぐためのものであることが明示されています。positionpositionInPixels は相互に依存する関係にあり、一方の変更がもう一方のウォッチャーをトリガーし、それが再び元のウォッチャーをトリガーする可能性がありました。特にResizeObserverのコールバック内でこの循環が発生すると、Chromiumはパフォーマンス保護のために警告を出力します。

値の比較による更新スキップは、ウォッチャーの構造自体を変更せずに循環を断ち切れる最小限の修正といえます。Reactiveなプロパティシステムではよくあるパターンであり、特にChromiumのResizeObserver実装の厳密さに対応するために有効です。

まとめ

本PRは、プロパティ相互参照による循環更新を条件チェックで遮断することで、Chromium特有のResizeObserverエラーを解消しています。3つのウォッチャーすべてに同じパターンを適用することで、一貫性を保ちながらパフォーマンスとブラウザ互換性を向上させた変更です。

記事メタデータ

Generated by:
Claude Sonnet 4.5 for DiffDaily

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術詳細(各論)→まとめ(結論)の3部構成が明確に守られています。設計判断のセクションも設けられており、読者の理解を深める構成になっています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```typescript:path/to/file.ts)、PR/Issue番号のリンク記法([#2018](URL))が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

ResizeObserver、循環参照、ウォッチャーといった専門用語を前提としており、専門知識を持つエンジニアという対象読者に適合した内容です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論の構成になっており、各段落もトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が守られています。可読性が非常に高いです。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているコード(split-panel.ts, split-panel.md)は、提供されたDiff情報と正確に一致しています。ファイルパスも正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「循環参照」「ウォッチャー」「ResizeObserver」などの技術用語が、PRのコンテキストと一般の用法に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

プロパティの相互監視による循環参照がResizeObserverエラーを引き起こすという説明は、Diff内のコード変更(条件チェックの追加)とコメントによって裏付けられており、技術的に正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(問題の原因、解決策、関連Issue)は、PRのDescription、Diff内のコード、コメントによって裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#2092)、Issue番号(#2018)などの数値や固有名詞はすべて正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

「ResizeObserverエラーを回避する循環参照の防止」というタイトルは、元のPRタイトル「Split panel resize bug」よりも具体的で、変更の核心を的確に表現しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事内で言及されている「Chromiumベースのブラウザ」という情報は、PRのchangelog.mdのDiffに記載されており、外部知識の捏造はありません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

「発生していました」「修正されました」といった過去形の表現は、完了した変更を説明する上で適切であり、時間表現に誤りはありません。