User reported "为什么画布是空的" — Bistro DeepSeek generation, layer
panel populated with the root frame but canvas fully blank mid-stream.
The MCP-side document showed children, the UI-side layer tree showed
the root, but no pixels rendered. Two structural issues converged:
1. ShadowEffect TS type marks offsetX / offsetY / blur / spread as
required, but LLM-emitted shadows routinely omit them
(`{type:'shadow', blur:3, color:'#0000001A'}` with no spread). The
prior (and the new shadow-cornerRadius) code multiplied the missing
field through cornerRadius / RRectXY math, producing NaN. CanvasKit's
RRectXY throws on NaN inside the WASM module, the throw escapes
drawNode (renderer.ts:326 had no try/catch), and the entire render
loop aborts past the bad node — so even unrelated siblings stop
drawing. User sees a fully empty canvas despite document state
being intact.
2. The drawNode loop had zero error isolation — a single malformed
node could blank the whole frame. Structural fragility independent
of the NaN bug; any future renderer regression would have the same
symptom.
Two fixes:
- applyShadowDirect coerces missing / non-finite shadow numeric
fields to 0 before any math (offsetX / offsetY / spread defaults
to 0; blur defaults to 0 and clamps non-negative). NaN can't reach
CanvasKit. The pre-existing drawRect path also benefits — the old
code happily fed NaN to drawRect via `x + shadow.offsetX -
shadow.spread`, just relied on Skia's tolerance for some NaN cases.
- renderer.ts wraps drawNode in per-node try/catch with a console.error
on failure. A bad node now logs and skips; siblings render normally.
Defense-in-depth so the next renderer regression doesn't blank the
canvas.
|
||
|---|---|---|
| .. | ||
| agent-native@22f20e42cd | ||
| pen-acp | ||
| pen-ai-skills | ||
| pen-core | ||
| pen-engine | ||
| pen-figma | ||
| pen-mcp | ||
| pen-react | ||
| pen-renderer | ||
| pen-sdk | ||
| pen-types | ||
| CLAUDE.md | ||