Skip to content

[C15][C16][C54] react: config and props handling — CanvasBox physics props aren't live, substeps silently dropped, DOM/canvas defaults diverge #16

Description

@GFier

From the 2026-07-06 codebase audit (docs/audits/codebase-audit-2026-07-06.md, in-repo). Finding IDs are stable — cite them in fixes.

Severity: High (C15, C16) + Medium (C54) · Status: CONFIRMED

C15 — CanvasBox physics props look controlled but aren't (canvas-box.tsx:89-104; canvas-elastica.tsx:274-282). The update effect covers mass, restitution, isStatic, width, height… and calls updateParticle — which only rewrites a Map entry. But mass/restitution/static are read exclusively inside the init block, and collision dimensions are baked at initialCondition (the engine reads rect only there). Animate <CanvasBox width={w}> 10→100: the drawn rect grows (renderer reads the Map each frame) while the collision body stays 10px until an unrelated re-init — visible interpenetration. mass={5} does nothing, ever, unless something else resets the world.

C16 — DomElastica silently drops solver.substeps (dom-elastica.tsx:100-135). stableConfig rebuilds solver from an allowlist {slop, percent, fixedDeltaTime}substeps (typed, documented in the README table) is discarded. config={{ solver: { substeps: 4 } }} → engine runs 1 substep, no warning. Canvas passes the raw config through — the identical config behaves differently per mode.

C54 — three config strategies, two default sets (dom-elastica.tsx:100-135 vs canvas-elastica.tsx:90-107). DOM: allowlist-reconstruction with its own DEFAULT_CONFIG (gridSize: 8) over engine defaults (4). Canvas: useMemo(() => config, [13 hand-picked deps]) — missing config?.solver?.substeps in the deps, so runtime substep changes are ignored. Net: <DomElastica> with no config runs gridSize 8/substeps dropped; <CanvasElastica> runs gridSize 4/substeps honored. The README claims one set of defaults for both (C12).

Direction

One shared useStableConfig hook, one source of defaults, spread config.solver instead of allowlisting. For C15: wire updateParticle to elastica.setMass/setRestitution + dimension updates, or document the props as init-only and remove them from the update effect.

Metadata

Metadata

Assignees

No one assigned

    Labels

    auditFinding from a codebase auditbugSomething isn't workinghighHigh severityreactpackages/react

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions