You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
plugin-calendar: object-calendar / view:calendar spread the authored node into ObjectCalendar — authored onDateClick / onNavigate throw uncaught, authored locale kills the render #4492
Measured while closing #4453 (the calendar-view renderer's consume-or-declare migration). That card's surface is calendar-view's renderer only, so this sibling registration is filed rather than fixed.
The mechanism
ObjectCalendarRenderer — registered as bothplugin-calendar:object-calendar and view:calendar (packages/plugin-calendar/src/index.tsx:45-81) — ends in the same raw spread #4453 removed from calendar-view (index.tsx:58, JSX tag spelled with a space after < so GitHub's body sanitizer does not eat it):
props is everything SchemaRenderer hands a registered widget: the node's authored keys, the contents of its props container, the injected runtime props and a host's trailing props. ObjectCalendarProps declares onEventClick, onRowClick, onDateClick, onEdit, onDelete, onNavigate, onViewChange, onEventDrop and locale (ObjectCalendar.tsx:64-81), so an authored value under any of those names lands on the declared prop — and an SDUI author writing JSON can never produce a function.
SchemaErrorBoundary: Component "plugin-calendar:object-calendar" failed to render / Incorrect locale information provided
The first two are the #4453 failure mode: React does not route event-handler errors to SchemaErrorBoundary, so they surface as uncaught window errors while the calendar keeps looking fine and that gesture is dead. onDateClick is additionally the unconditional shape — ObjectCalendar.tsx:596 tests if (onDateClick) and a non-empty string is truthy, so the guard passes the value straight to a call.
locale is a render-time crash: any string Intl rejects throws out of toLocaleDateString. en_US (the underscore spelling a producer writes by accident) is the realistic case; '', '123' and 'a' throw the same way, while 'garbage' happens to be a well-formed tag and does not.
Not reproduced, recorded honestly: authored onEventClick did not throw in the probe's default configuration. ObjectCalendar.tsx:585-592 only calls the parent handler when the local navigation is not an overlay (if (!navIsOverlay)), and the probe resolved to an overlay, so the call was skipped. The exposure is in the code path; its reachability depends on the navigation mode and was not established here.
Fix shape
The #4425 phase-2 ruling applied to this renderer, exactly as #4453 did for calendar-view: replace the raw spread with consume-or-declare — declared registry inputs consumed, ObjectCalendarProps' callbacks kept as a declared function-typed host hatch (a host-passed function must keep working), locale accepted only when Intl.getCanonicalLocales takes it, everything else dropped. #4453's renderer is the worked example, including the resolvers and the pin file (packages/plugin-calendar/src/calendar-view-renderer.propsContract.test.tsx).
Note the two registrations share one implementation, so one fix closes object-calendar and view:calendar together — and both are plugin-calendar targets in the #4425 DOM-leak sweep ledger, which does not measure this class (a crash-free spread onto a component that declares its props leaks nothing to the DOM).
Related: #4453 (the same defect on calendar-view, fixed), #4425 (the whitelist contract), #4433 / #4452 (the two earlier collisions on the same spread), #4454 (allowCreate, unrelated but same widget family).
Ruling (delegated authority; open veto window): apply the #4453 pattern (PR #4494) to the shared ObjectCalendarRenderer behind object-calendar / view:calendar — consume-or-declare, no raw spread into ObjectCalendar:
Red-first = the card's own measured repros: authored onDateClick: 'NOT-A-FUNCTION' → day-cell click throws uncaught pre-fix, no-op post-fix; authored onNavigate string → Next-click same; authored locale: 'en_US' → error boundary pre-fix, default-locale render post-fix. Use the fix(plugin-calendar): calendar-view consumes or declares every forwarded prop — authored onEventClick can no longer crash a click (#4453) #4494 union-of-channels error capture (window event + sync throw + console.error). The honestly-unproven onEventClick path: cover it under the same declared-hatch rule and pin the drop, but do NOT claim a pre-fix crash repro the filing could not prove — assert the contract, state the provenance.
Sequencing gate: PR #4494 in origin/main first (armed, CI green — poll ~180s, ≤40min; report BLOCKED otherwise). Also re-read in-flight #4434's claim comment before running the sweep — it must still be judge-internals-only.
Grading: patch @object-ui/plugin-calendar unless the emitted .d.ts moves (measure both ways; minor per precedent if the published surface grows). Never major.
Surface (mutual exclusion): the ObjectCalendarRenderer source file + one new pin test + one changeset, all in packages/plugin-calendar/**. ⛔ NOT: calendar-view-renderer.tsx (landed by #4494 — read-only reference), ObjectCalendar.tsx/CalendarView.tsx component internals (boundary-only fix; if the fix genuinely requires a component change, STOP and report), the sweep file, console/**, chart files (#4466 in flight), content/docs/releases/. #4493/#4454 (inert inputs) stay their own pooled pair — census-confirm only.
Activity
yinlianghui commentedon Aug 12, 2026
CLAIM — session
session_017Qqyix2QcnpUC9XeYVDzx3, branchclaude/issue-4492-objectcalendar-props-contract.Ruling (delegated authority; open veto window): apply the #4453 pattern (PR #4494) to the shared
ObjectCalendarRendererbehindobject-calendar/view:calendar— consume-or-declare, no raw spread intoObjectCalendar:ObjectCalendar's declared callback props;localevalidated withIntl.getCanonicalLocales(the fix(plugin-calendar): calendar-view consumes or declares every forwarded prop — authored onEventClick can no longer crash a click (#4453) #4494 lesson —typeof stringleaves the measured RangeError crash open); numeric knobs validated as finite where present.onDateClick: 'NOT-A-FUNCTION'→ day-cell click throws uncaught pre-fix, no-op post-fix; authoredonNavigatestring → Next-click same; authoredlocale: 'en_US'→ error boundary pre-fix, default-locale render post-fix. Use the fix(plugin-calendar): calendar-view consumes or declares every forwarded prop — authored onEventClick can no longer crash a click (#4453) #4494 union-of-channels error capture (window event + sync throw + console.error). The honestly-unprovenonEventClickpath: cover it under the same declared-hatch rule and pin the drop, but do NOT claim a pre-fix crash repro the filing could not prove — assert the contract, state the provenance.onEventClickreaches CalendarView through the spread and throws an UNCAUGHT error on click — needs a contract decision, not a strip #4453/plugin-calendar: authoringeventson acalendar-viewnode crashes the component — the SDUI action object overwrites the computed CalendarEvent array #4433/fix(plugin-calendar): authored ISO currentDate is parsed to a Date instead of crashing the calendar (#4452) #4484 sibling pins stay green; the DOM-leak sweep (read-only — finding: the DOM-leak "is this attribute HTML-defined" judge now exists in two copies, in two test files that cannot import each other #4434 in flight owns judge internals, you own NOTHING in that file) stays green.Sequencing gate: PR #4494 in
origin/mainfirst (armed, CI green — poll ~180s, ≤40min; report BLOCKED otherwise). Also re-read in-flight #4434's claim comment before running the sweep — it must still be judge-internals-only.Grading: patch
@object-ui/plugin-calendarunless the emitted.d.tsmoves (measure both ways; minor per precedent if the published surface grows). Never major.Surface (mutual exclusion): the
ObjectCalendarRenderersource file + one new pin test + one changeset, all inpackages/plugin-calendar/**. ⛔ NOT:calendar-view-renderer.tsx(landed by #4494 — read-only reference),ObjectCalendar.tsx/CalendarView.tsxcomponent internals (boundary-only fix; if the fix genuinely requires a component change, STOP and report), the sweep file, console/**, chart files (#4466 in flight),content/docs/releases/. #4493/#4454 (inert inputs) stay their own pooled pair — census-confirm only.Generated by Claude Code
Generated by Claude Code
fix(plugin-calendar): ObjectCalendar's renderer consumes or declares …