Skip to content

fix: fire computed listeners for Temporal values#656

Merged
jmeistrich merged 2 commits into
LegendApp:mainfrom
momomuchu:fix/temporal-computed-listeners-650
Jul 4, 2026
Merged

fix: fire computed listeners for Temporal values#656
jmeistrich merged 2 commits into
LegendApp:mainfrom
momomuchu:fix/temporal-computed-listeners-650

Conversation

@momomuchu

Copy link
Copy Markdown
Contributor

Computed observables that wrap a Temporal.* value never fire their listeners on change (#650). Temporal instances have no enumerable own properties, so the change-diff treats them as empty objects and decides nothing changed.

Temporal values are now detected (duck-typed via Symbol.toStringTag, which every Temporal type sets to "Temporal.<Type>", so it works whether the runtime has native Temporal or a polyfill) and treated as opaque primitive-like values compared by their string form, mirroring the existing Date handling. Wired into the same isObject/isPrimitive/equals spots that already special-case Date.

Added tests: a computed returning a Temporal.PlainDate/Instant notifies on change and does not notify when the value is equal. They fail without the fix (the listener fires once instead of twice) and pass with it. @js-temporal/polyfill is added as a dev-only dependency so the tests can run on Node, which has no native Temporal yet. tsc, eslint and prettier clean.

Closes #650

Temporal.* instances have no enumerable own properties, so the change
diff in updateNodesAndNotify treated them as empty objects and skipped
notifications, mirroring the same issue Date already handles.

Add an isTemporal guard (duck-typed via Symbol.toStringTag so it works
without a global Temporal) and treat Temporal instances as opaque,
primitive-like values compared by their string representation, the same
way Date is compared by timestamp.

Fixes LegendApp#650

@jmeistrich jmeistrich left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good! Just one small tweak to a test and I think we can merge :)

Comment thread tests/computed.test.ts Outdated
expect(handler).toHaveBeenCalledTimes(1);

// Setting to a string that resolves to an equal PlainDate should not re-notify.
source$.set('2024-01-15');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this is the same as the original string on line 295, should be different to make sure it's testing correctly?

Addresses review feedback on LegendApp#650: the equal-PlainDate test now sets a
different string that still resolves to the same PlainDate, so it exercises
value-equality rather than raw-string identity.
@momomuchu

Copy link
Copy Markdown
Contributor Author

Good catch. Updated line 306 to set '2024-01-15T10:30:00', a different source string that still resolves to the same PlainDate, so the test now exercises value-equality rather than raw-string identity. Thanks!

@jmeistrich jmeistrich merged commit 81dd037 into LegendApp:main Jul 4, 2026
3 checks passed
@jmeistrich

Copy link
Copy Markdown
Member

Merged! Thank you!

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.

Temporal objects in computed observables don't trigger derived notifications

2 participants