Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider removing fallback paths in CalendarFields and CalendarMergeFields #2310

Closed
anba opened this issue Jun 17, 2022 · 7 comments · Fixed by #2467
Closed

Consider removing fallback paths in CalendarFields and CalendarMergeFields #2310

anba opened this issue Jun 17, 2022 · 7 comments · Fixed by #2467
Assignees
Labels
normative Would be a normative change to the proposal spec-text Specification text involved
Milestone

Comments

@anba
Copy link
Contributor

anba commented Jun 17, 2022

CalendarFields and CalendarMergeFields both have fallback paths when "fields" resp. "mergeFields" isn't present. This approach isn't used anywhere else in the Temporal spec, for example all other Calendar API methods are required and will throw an error when they aren't present on an Calendar-like object.

I'm not sure if this is just a left-over from the initial design, which had more fallback paths. For example certain Temporal.TimeZone.prototype methods didn't contain brand checks and were applicable for any object. One example:

The minimal implementation for both methods is relatively simple, so it shouldn't be too much to ask that users provide their own implementation.

  • fields just needs to return its input.
  • mergeFields combines both objects and has to perform some special-casing for "month" and "monthCode".

It's also worth noting that user-defined calendars which use fields like "era" and "eraYear" have to define their own version of mergeFields anyway.

Minimal implementation example:

class MyCalendar {
  // Other methods omitted.

  fields(fieldNames) {
    return fieldNames;
  }

  mergeFields(fields, additionalFields) {
    if ("month" in additionalFields || "monthCode" in additionalFields) {
      let {month, monthCode, ...rest} = fields;
      return {...rest, ...additionalFields};
    }
    return {...fields, ...additionalFields};
  }
}
@ptomato
Copy link
Collaborator

ptomato commented Jun 20, 2022

I believe we did keep these intentionally even though the rest of the fallbacks were not present, because many userland calendars wouldn't have to have these. I don't feel strongly either way though.

@ptomato ptomato added this to the Stage "3.5" milestone Dec 8, 2022
@ptomato
Copy link
Collaborator

ptomato commented Dec 8, 2022

cc @sffc

@ptomato ptomato added spec-text Specification text involved normative Would be a normative change to the proposal and removed meeting-agenda labels Jan 5, 2023
@ptomato
Copy link
Collaborator

ptomato commented Jan 5, 2023

In the champions meeting of 2023-01-05 we decided to accept @anba's recommendation to remove these in order to reduce complexity in the proposal.

@ljharb
Copy link
Member

ljharb commented Jan 13, 2023

@ptomato i'm not seeing anything in here that explains the benefits of removing the fallbacks. All I've seen is points about how it might not be that harmful to remove them.

ptomato added a commit that referenced this issue Jan 13, 2023
Note, DefaultMergeCalendarFields still exists in this branch but one use
of it would be removed in #2310, and #1418 would consolidate this
definition of Temporal.Calendar.prototype.mergeFields() with the earlier
one in the 262 part of the proposal. So ultimately, this would be the only
definition of mergeFields.

To do, if we decide this is the right approach:
- Check that all the places that might produce abrupt completions are
  correct
- Change the reference code to follow this spec
ptomato added a commit that referenced this issue Jan 20, 2023
This pulls as much logic as possible out of the calendar-dependent
operation into algorithm steps that are common to all calendars, in order
to address the implementor questions about the previous definition of the
operation.

Note, there is the potential for a rebase conflict with #2310, which
removes one use of DefaultCalendarMergeFields and renames it to
ISOCalendarMergeFields.
ptomato added a commit that referenced this issue Jan 26, 2023
This pulls as much logic as possible out of the calendar-dependent
operation into algorithm steps that are common to all calendars, in order
to address the implementor questions about the previous definition of the
operation.

Note, there is the potential for a rebase conflict with #2310, which
removes one use of DefaultCalendarMergeFields and renames it to
ISOCalendarMergeFields.
ptomato added a commit that referenced this issue Feb 3, 2023
This pulls as much logic as possible out of the calendar-dependent
operation into algorithm steps that are common to all calendars, in order
to address the implementor questions about the previous definition of the
operation.

Note, there is the potential for a rebase conflict with #2310, which
removes one use of DefaultCalendarMergeFields and renames it to
ISOCalendarMergeFields.
ptomato added a commit that referenced this issue Feb 7, 2023
This pulls as much logic as possible out of the calendar-dependent
operation into algorithm steps that are common to all calendars, in order
to address the implementor questions about the previous definition of the
operation.

Note, there is the potential for a rebase conflict with #2310, which
removes one use of DefaultCalendarMergeFields and renames it to
ISOCalendarMergeFields.
@ljharb
Copy link
Member

ljharb commented Feb 11, 2023

@ptomato i understand this has consensus, but nobody yet has explained why this is a good thing.

@ptomato
Copy link
Collaborator

ptomato commented Feb 14, 2023

Sorry, I assumed this had been answered by the slide I presented. Here's a slightly more elaborate, non-slide-deck-based explanation:

There were two reasons to have these fallbacks:

  1. Guard against deleting properties off the prototype: delete Temporal.Calendar.prototype.fields and delete Temporal.Calendar.prototype.mergeFields.
  2. Convenience when implementing the Calendar protocol with a plain object (that doesn't extend Temporal.Calendar)

With the optimization from #1808 adopted, built-in calendars no longer observably look up methods. Guarding against deleted prototype properties is no longer necessary in most cases, because built-in calendars will continue to work the same if those properties are deleted.

Also with #1808, we now require objects implementing the Calendar protocol to implement all of the methods anyway, so that we can unambiguously say whether an object implements the protocol or not — the way we distinguished this previously was a confusing, weird corner of the proposal, which is now able to be eliminated altogether. So omitting fields and mergeFields implementations for convenience on plain objects is no longer a thing, because they must be present in order for the object to be considered to implement the protocol.

With those two reasons no longer applying, we didn't see any reason to push back against the request for less complexity. So as a literal answer to your question, I guess "less complexity, because it turned out not to be needed" is the good thing.

@ljharb
Copy link
Member

ljharb commented Feb 14, 2023

Gotcha, thanks for typing it out.

ptomato added a commit that referenced this issue Feb 15, 2023
This pulls as much logic as possible out of the calendar-dependent
operation into algorithm steps that are common to all calendars, in order
to address the implementor questions about the previous definition of the
operation.

Note, there is the potential for a rebase conflict with #2310, which
removes one use of DefaultCalendarMergeFields and renames it to
ISOCalendarMergeFields.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
normative Would be a normative change to the proposal spec-text Specification text involved
Projects
None yet
4 participants