LearnNewsExamplesServices
Frontmatter
id19172
titleDateSelector throws when weekStartDay changes during a month slide
stateClosed
labels
bugai
assigneessloemo01
createdAtSep 24, 2026, 5:01 PM
updatedAtOct 7, 2026, 2:27 PM
githubUrlhttps://github.com/neomjs/neo/issues/19172
authorneo-opus-grace
commentsCount3
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtOct 7, 2026, 2:27 PM

DateSelector throws when weekStartDay changes during a month slide

neo-opus-grace
neo-opus-grace commented on Sep 24, 2026, 5:01 PM

Reserved for @sloemo01, who found it while writing #19006's month-grid witness (#19171). The maintainer team will not claim it. It is a natural next step from that spec: the red arm already half-exists there.

Context

#19171's weekend arm moves weekStartDay first and the month second, and it waits for the sidebar's day names in between. Its comment explains why: run the other way round, the pair crashed. The PR works around the crash; this issue reports it.

Reproduced on #19171's head f42ce1f9b3, which changes no file under src/:

  1. Mount the calendar-month component fixture.
  2. Move currentDate from February to August 2027.
  3. Immediately afterwards, set weekStartDay: 1.

The page throws Cannot set properties of undefined (setting 'transform'), and the fixtures' worker-error gate fails the test. The month grid itself ends correct, with row 6 starting on 2027-07-26. Only the sidebar DateSelector throws.

The Problem

A user who changes the week's first day in the calendar settings while the sidebar is still sliding to another month gets an uncaught error. The same applies to any code that moves both values back to back.

The Architectural Reality

  • DateSelector#changeMonth (src/component/DateSelector.mjs:461) starts a slide by wrapping the day view in an animation wrapper.
  • changeMonthTransitionCallback (:520-525) later writes me.vdom.cn[1].cn[0].style.transform.
  • afterSetWeekStartDay (:397-399) calls recreateDayViewContent(false, false), which rebuilds the day view in place.

The likely mechanism is an inference, still to be confirmed by the red arm below: the rebuild lands while the slide is in flight, so the callback reads a node that is no longer the wrapper and has no style.

The Fix

A config change during a month transition must not read or reshape the transition's vdom. Two plausible shapes:

  • defer the day-view rebuild until isUpdating clears;
  • have the callback re-resolve its wrapper and stand down when it is gone.

Choose from the red arm, not from this sketch.

Acceptance Criteria

  • A component arm that moves the month and then weekStartDay back to back is red before the fix: the page error above.
  • After the fix, that arm is green: no page error, the month grid's row 6 starts 2027-07-26, and the sidebar's day names start with Monday.
  • #19171's weekend arm no longer needs its ordering: its comment is updated to point here.

Related

#19171 · #19006 · #19149 (the same contributor's previous finding)

Sweeps at 15:00Z:

  • Live latest-open: the latest 20 open issues; none equivalent.
  • Org search (DateSelector transform, changeMonthTransitionCallback, DateSelector weekStartDay): only #175, closed and unrelated.
  • A2A: no claim.

Retrieval Hint: "DateSelector weekStartDay month slide transform crash changeMonthTransitionCallback"

Origin Session ID: 1f7129c9-c0f7-42e0-ba47-7a42e5ac57c2

Authored by Grace (Claude Opus 5.5, Claude Code) 🖖

sloemo01 referenced in commit 9396475 - "test(calendar): cite #19172 in arm 4's ordering comment (#19006)" on Sep 24, 2026, 5:53 PM
sloemo01 referenced in commit 8ce4205 - "test(calendar): cite #19172 in arm 4's ordering comment (#19006)" on Sep 24, 2026, 5:54 PM
tobiu referenced in commit 5447bf6 - "test(calendar): the month grid's structure, pinned to derived dates (#19006) (#19171) on Sep 24, 2026, 7:01 PM
sloemo01
sloemo01 Sep 27, 2026, 8:23 AM

Claiming this one, following up on #19171.

Plan: a component arm in the calendar-month fixture that moves currentDate to August and then weekStartDay back to back, the order that crashes today, red before the fix with the worker-error gate catching the transform error. Then the fix chosen from what that arm shows: either the day-view rebuild defers while isUpdating is set, or changeMonthTransitionCallback re-resolves its wrapper and stands down when it is gone. AC3 included: #19171's weekend arm loses its ordering workaround and its comment points here.

Everything the ticket asks for is verifiable locally, the component tier runs from the checkout alone.

tobiu assigned to @sloemo01 on Sep 27, 2026, 9:49 AM
sloemo01 cross-referenced by PR #19447 on Oct 7, 2026, 2:13 PM
sloemo01
sloemo01 Oct 7, 2026, 2:14 PM

The red arm is up and reproduces the ticket exactly, and the fix is in on fix/19172-dateselector-weekstartday-mid-slide.

The red arm. test/playwright/component/calendar/DateSelectorWeekStartDayMidSlide.spec.mjs drives the calendar-month fixture twice (setCurrentDate, then setWeekStartDay, two separate driver imports because the first write has to start the sidebar's slide before the second lands). Before the fix:

pageerror: Cannot set properties of undefined (setting 'transform')
    at DateSelector.changeMonthTransitionCallback (src/component/DateSelector.mjs:525:45)

That is the crash the ticket reported, verbatim, on the pair of writes the ticket names.

The mechanism, confirmed by the arm rather than by reading. changeMonth parks the month content in an animation wrapper at vdom.cn[1] and starts the slide; changeMonthTransitionCallback then writes vdom.cn[1].cn[0].style.transform. The day-view rebuild that afterSetWeekStartDay runs wipes that same wrapper's children (getCenterContentEl().cn = []), so the callback's read lands one level down on a node with no style. The inference in the ticket holds.

The fix. recreateDayViewContent now caches its arguments and defers while isUpdating is set, the window where the transition owns the center element; afterSetIsUpdating(false) replays it. The slide's own callbacks keep their wrapper, and the rebuild lands after the transition settles. This is the first of the two shapes the ticket sketched (defer the rebuild until isUpdating clears); the second is unnecessary once the first is in place.

On the same branch: DateSelectorWeekStartDayMidSlide green, and AC-3 done, arm 4 of MonthGridStructure.spec.mjs loses its ordering comment and now notes that either write order is safe ([#19172]).

sloemo01
sloemo01 Oct 7, 2026, 2:14 PM

The branch is up as #19447 (targeting dev). Red arm, fix and AC-3 are on it; CI is running. The one deviation from the comment above: the arm drives the pair as two separate driver imports, because a single import writing both values never enters the race window and passes on unfixed code.

tobiu referenced in commit f0c7110 - "fix(component): the DateSelector day-view rebuild defers while a month transition runs (#19172) (#19447)" on Oct 7, 2026, 2:27 PM
tobiu closed this issue on Oct 7, 2026, 2:27 PM