Problem
Temporal.PlainDate (and the other Temporal.* types) intentionally throw when .valueOf() is called — they reject implicit numeric coercion by design:
TypeError: Do not use Temporal.PlainDate.prototype.valueOf;
use Temporal.PlainDate.prototype.compare for comparison.
microdiff's equality check on line 36 of dist/index.js uses +objKey === +newObjKey, which triggers .valueOf() and throws when either value is a Temporal type.
Reproduction
import diff from "microdiff";
const before = { date: Temporal.PlainDate.from("2024-03-15") };
const after = { date: Temporal.PlainDate.from("2024-06-01") };
diff(before, after);
// → TypeError: Do not use Temporal.PlainDate.prototype.valueOf
Relevant code
// dist/index.js:34-36
!(areCompatibleObjects &&
(isNaN(objKey)
? objKey + "" === newObjKey + "" // string coercion — works
: +objKey === +newObjKey)) // numeric coercion — throws for Temporal
Temporal.PlainDate is an object, typeof is "object", and it isn't in the richTypes allow-list, so the code reaches the +objKey path and explodes.
Possible fixes
- Add
Temporal.PlainDate (and siblings) to richTypes so they get string-compared instead of numeric-compared.
- Wrap the
+objKey coercion in a try/catch and fall back to string comparison.
- Check for a
Symbol.toPrimitive or valueOf override that throws before attempting numeric coercion.
Option 1 is the smallest change but requires enumerating Temporal types. Option 2 is more resilient to future types that also reject .valueOf().
Context
Temporal is currently Stage 3 and shipping behind --harmony-temporal in V8 / Node.js 22+. It will become increasingly common as a Date replacement.
Problem
Temporal.PlainDate(and the otherTemporal.*types) intentionally throw when.valueOf()is called — they reject implicit numeric coercion by design:microdiff's equality check on line 36 of
dist/index.jsuses+objKey === +newObjKey, which triggers.valueOf()and throws when either value is a Temporal type.Reproduction
Relevant code
Temporal.PlainDateis an object,typeofis"object", and it isn't in therichTypesallow-list, so the code reaches the+objKeypath and explodes.Possible fixes
Temporal.PlainDate(and siblings) torichTypesso they get string-compared instead of numeric-compared.+objKeycoercion in a try/catch and fall back to string comparison.Symbol.toPrimitiveorvalueOfoverride that throws before attempting numeric coercion.Option 1 is the smallest change but requires enumerating Temporal types. Option 2 is more resilient to future types that also reject
.valueOf().Context
Temporal is currently Stage 3 and shipping behind
--harmony-temporalin V8 / Node.js 22+. It will become increasingly common as aDatereplacement.