Skip to content

fix: exportAsHtml の埋め込み画像に累積バイト数上限を追加 (#354)#355

Merged
ymnao merged 2 commits into
mainfrom
fix/export-html-total-embed-bytes-cap
Jul 18, 2026
Merged

fix: exportAsHtml の埋め込み画像に累積バイト数上限を追加 (#354)#355
ymnao merged 2 commits into
mainfrom
fix/export-html-total-embed-bytes-cap

Conversation

@ymnao

@ymnao ymnao commented Jul 18, 2026

Copy link
Copy Markdown
Owner

概要

exportAsHtml で埋め込む base64 画像の累積バイト数に上限 (256MB) を設け、renderer OOM リスクを graceful degradation で回避 (#354)。個別ファイル上限 (main 側 64MB) を通り抜けた画像でも、累積が V8 heap を圧迫する前に skip して元 src を維持する。

関連 Issue

closes #354

移行 Stage

  • Stage 5: OGP / PDF / アップデート (HTML export post-processor の強化)

変更内容

  • TOTAL_EMBED_BYTES_LIMIT = 256MB (base64 文字列長) を resolve-html-images.ts に追加
  • embedHtmlImagesAsDataUri の worker で read 完了後に累積判定 → 超過なら continue で data URI 化を skip し元 src を維持 (broken image と同じ経路)
  • 単スレッド JS の check → += 間 await 無しで実オーバーシュートは発生しない旨をコメントで明示
  • JSDoc に cap 到達後の挙動と「skip 対象は I/O 完了順に依存」を追記
  • test 追加 2 件: 3 img の 3 個目 skip / 単発上限超過の境界

動作確認

  • vitest run src/lib/resolve-html-images.test.ts — 19/19 pass (新規 2 件を含む)
  • vitest run — 2578/2578 pass (前 main 2576 + 新規 2)
  • tsc -p tsconfig.web.json --noEmit / tsc -p tsconfig.node.json --noEmit clean
  • biome check clean
検証エビデンス

リスク分類

tier: medium — 一般的な変更 (単一 IPC でも security 境界でもないが、renderer heap 保護目的の防御コードのため medium 相当で codex security を実行)

実行した検証

種別 コマンド 結果
テスト ./node_modules/.bin/vitest run PASS 2578 (skipped 2)
テスト ./node_modules/.bin/vitest run src/lib/resolve-html-images.test.ts PASS 19/19
Typecheck ./node_modules/.bin/tsc -p tsconfig.web.json --noEmit PASS
Typecheck ./node_modules/.bin/tsc -p tsconfig.node.json --noEmit PASS
Lint ./node_modules/.bin/biome check src/lib/resolve-html-images.ts src/lib/resolve-html-images.test.ts PASS (0 fixes)
レビュー codex-review security PASS (0 findings)

レビュー指摘と対応

/simplify (4 angle 並列):

  • Reuse: clean
  • Simplification: 2 tests の helper 抽出提案 → SKIP (premature abstraction、2 例で helper 化は過剰)
  • Efficiency (a): cap 超過画像も read してから捨てる無駄 → SKIP (事前 stat の新規 IPC が必要、スコープ超)
  • Efficiency (b): 300MB 文字列 alloc で test 重い → SKIP (constant param 化すると real value drift 検出できず coverage 弱化)
  • Altitude (a): BoundedByteBudget 抽象化 → SKIP (単一 caller で hard-coding 妥当、agent 自身も同結論)
  • Altitude (b): TOTAL_EMBED_BYTES_LIMIT = EMBED_CONCURRENCY * MAX_READ_FILE_BYTES derivation → SKIP (renderer heap 予算と main peak 保護は別関心、意図的に drift 可能)

/code-review medium (8 finder → verify):

codex-review security: PASS (0 findings)

追跡先

なし

Draft 判定

  • 判定: normal
  • 根拠: step 4 — codex-review security PASS + /simplify / /code-review の findings は commit 456866e で解消済、追跡 issue 化する未対応残なし

ymnao added 2 commits July 19, 2026 01:33
- TOTAL_EMBED_BYTES_LIMIT = 256MB (base64 文字列長) を導入
- worker で read 完了後、累積 + 今回分が上限超過なら data URI 化を skip し
  元 src を維持 (broken image と同じ graceful degradation 経路)
- worker 並列で最大 K-1 個のオーバーシュートは許容 (実害なし)
- test 追加: 3 img で 3 個目が skip される / 単発上限超過の境界
- JSDoc に cap 到達後の挙動 (skip + 元 src 維持) と I/O 完了順依存を追記
- 「K-1 オーバーシュート許容」コメントは誤り (check と += の間に await が
  無いため JS 単スレッド性で他 worker 割り込み不可) → 事実に合わせて修正
@ymnao
ymnao merged commit fc1c423 into main Jul 18, 2026
9 checks passed
@ymnao
ymnao deleted the fix/export-html-total-embed-bytes-cap branch July 18, 2026 16:57
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.

exportAsHtml: 埋め込み画像の累積バイト数に上限を設ける (renderer OOM 対策)

1 participant