tc39 / proposal-temporal

Provides standard objects and functions for working with dates and times.
https://tc39.es/proposal-temporal/docs/
Other
3.24k stars 148 forks source link

size-suggestion: collapse `toJSON` methods? #2858

Closed justingrant closed 1 month ago

justingrant commented 3 months ago

There are 11 toJSON methods in Temporal. Could ECMA-262 special-case Temporal objects in JSON.stringify to remove the need for all those methods?

SimenB commented 3 months ago

Lots of custom serializers rely on toJSON (e.g. pretty-format, downloaded 80M times a week, https://github.com/jestjs/jest/blob/0d222c1609e616333db16c6cff5de04e04aad222/packages/pretty-format/src/index.ts#L226), not just JSON.stringify.

littledan commented 3 months ago

It'd be unfortunate to add special logic to JSON.stringify; Temporal should follow normal conventions as much as possible. It would be nice if we could reuse the toString method in the toJSON property, but this is risky because of how the key argument is passed to toJSON, and then our toString function takes options. I'd prefer to leave things how they are.

justingrant commented 3 months ago

Meeting 2024-05-23: At the upcoming June 2024 TC39 plenary meeting, we'll propose specifying toJSON to have a single implementation that's shared among all Temporal types, saving 10 methods.

anba commented 3 months ago

The various toJSON methods have different function bodies, so using a single implementations seems strange. valueOf (#2857) has at least the same shared step across all function bodies, but that doesn't apply to toJSON. And if toJSON is changed to a single method, why stop there and have different toString, until, etc. methods?

ptomato commented 3 months ago

My idea was to basically have the body of the shared toJSON be the equivalent of return this.toString(); either with or without a brand check. I believe (but still need to confirm) that toJSON in the current spec text is always equivalent to calling toString with no options.

ptomato commented 3 months ago

I checked this, and the result of toJSON is always equivalent to calling toString with no arguments.

I have an implementation of this here.

It's a bit weird that we would be introducing another observable call, along with all the associated Unlike consolidating the valueOf methods which I think is a no-brainer, I'm neutral about this one. if everyone else thinks the benefits outweigh the drawbacks, and the plenary is OK with it, we should go ahead, but it's maybe a bit more dubious than some of the other things we're proposing.

What I would not want to do is consolidate these methods while eliminating the toString call, because that means we'd basically have a big switch statement based on the type of the receiver. Anba already mentioned that would be strange, and I think that's something implementations can choose to do anyway if they are so inclined, without identity equality between all the toJSON methods.

anba commented 3 months ago

valueOf and toJSON are part of broader object interface, so we really shouldn't create any Temporal-specific rules, but instead if we add new rules (like using a single aliased function for toJSON which delegates to toString), they should also apply to other (future) proposals.

ljharb commented 3 months ago

Date shouldn't be something we need to be consistent with - the brand checks are an improvement and one Temporal needs to keep.

justingrant commented 3 months ago

Would keeping brand checks prevent the function from being re-used by many different ECMAScript built-in objects?

anba commented 3 months ago

Yes, a brand check prevents the function from being reused by possible future proposals. (Unless those proposals extend the brand check with their own types.) In general I don't think we do brand-check followed by generic code, do we? A brand check is always followed by accessing some internal state which is only accessible after a successful brand check.

justingrant commented 3 months ago

Meeting 2024-05-30:

justingrant commented 2 months ago
  • @sffc to talk with @shu about how much savings this would be, and whether there's some other option that can combine implementations without having to change the spec.

@sffc - any luck on this? Trying to figure out what to say about this one in our Helsinki slides.

sffc commented 2 months ago

The response I received (and @shu can clarify) was that there would likely be a memory savings due to having fewer JSFunctions, but serialization is a hot path and it's questionable whether it's worth deviating from the norm.

I do personally think it is worthwhile discussing / acting plenary about this.

ptomato commented 2 months ago

I think if V8 wants the memory savings, they can get most of it already by multiplexing the toJSON builtins on the C++ side, and in that case we wouldn't have to add a weird anomaly to the spec which would make the multiplexing mandatory for all implementations.

ptomato commented 2 months ago

(In other words, if we're not going to have generic code that looks up toString, I think it's better not to do this. Happy to still present it in the slides, alternatively we could decide to withdraw that commit, whatever...)

ptomato commented 2 months ago

Conclusion from the TC39 plenary of 2024-06-12 is that we will wait for Mozilla to investigate the feasibility/desirability of this, and possibly bring it back at the July plenary.

dminor commented 1 month ago

Our position is that we should make all other proposed changes to reduce the size of Temporal first, and only do this if we get feedback that Temporal is still too large to ship.

ptomato commented 1 month ago

Thanks. Closing this, will reopen if that condition is met.