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

Normative: Validate receiver fields before fields of any param objects #2478

Merged
merged 3 commits into from
Feb 1, 2023

Conversation

ptomato
Copy link
Collaborator

@ptomato ptomato commented Jan 16, 2023

Changes to the order of observable operations in

  • PlainDate.p.with
  • PlainDateTime.p.with
  • PlainMonthDay.p.with
  • PlainTime.p.with
  • PlainYearMonth.p.since
  • PlainYearMonth.p.until
  • PlainYearMonth.p.with
  • ZonedDateTime.p.with

Swapping the PrepareTemporalFields calls in ZonedDateTime.p.with exposed another unnecessary user call: the 'timeZone' field was observably read from the receiver and from the object returned from mergeFields(), but never used. This is fixed as well.

Closes: #2462

Comment on lines -236 to +238
1. Let _partialTime_ be ? ToTemporalTimeRecord(_temporalTimeLike_, ~partial~).
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Let _partialTime_ be ? ToTemporalTimeRecord(_temporalTimeLike_, ~partial~).
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's debatable whether we'd want to make this change to PlainTime, which doesn't use PrepareTemporalFields, but it seems most consistent with the form suggested by Richard in #2462 (comment)

Copy link
Collaborator

Choose a reason for hiding this comment

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

👍
But if this is awkward and options never affects the interpretation of the first argument, then it would also be coherent to move every Set _options_ to ? GetOptionsObject(_options_). to follow full consumption (with constituent validation) of the first argument by PrepareTemporalFields/ToTemporalTimeRecord/etc.—although that is not my preference because it's not clear to me in that case whether GetOptionsObject should precede or follow integration of receiver and argument data in e.g. CalendarMergeFields.

@codecov
Copy link

codecov bot commented Jan 16, 2023

Codecov Report

Merging #2478 (f35fc58) into main (189e689) will decrease coverage by 0.03%.
The diff coverage is 100.00%.

❗ Current head f35fc58 differs from pull request most recent head f25466a. Consider uploading reports for the commit f25466a to get more accurate results

@@            Coverage Diff             @@
##             main    #2478      +/-   ##
==========================================
- Coverage   94.97%   94.95%   -0.03%     
==========================================
  Files          20       20              
  Lines       10907    10817      -90     
  Branches     1996     1957      -39     
==========================================
- Hits        10359    10271      -88     
  Misses        487      487              
+ Partials       61       59       -2     
Impacted Files Coverage Δ
polyfill/lib/ecmascript.mjs 98.29% <100.00%> (-0.01%) ⬇️
polyfill/lib/plaindate.mjs 99.66% <100.00%> (-0.01%) ⬇️
polyfill/lib/plaindatetime.mjs 97.23% <100.00%> (ø)
polyfill/lib/plainmonthday.mjs 97.67% <100.00%> (ø)
polyfill/lib/plaintime.mjs 98.26% <100.00%> (ø)
polyfill/lib/plainyearmonth.mjs 98.36% <100.00%> (-0.01%) ⬇️
polyfill/lib/zoneddatetime.mjs 99.82% <100.00%> (-0.01%) ⬇️
polyfill/runtest262.mjs 100.00% <0.00%> (+10.00%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

ptomato added a commit to ptomato/test262 that referenced this pull request Jan 16, 2023
The with() methods, as well as PlainYearMonth's since() and until(), were
adjusted to read the receiver's fields before the fields of any objects
provided as arguments. This change is observable, so affects several tests
that test the observed order of operations.

Normative PR: tc39/proposal-temporal#2478
@ptomato
Copy link
Collaborator Author

ptomato commented Jan 16, 2023

Test262 updates are in tc39/test262#3769

polyfill/lib/plaindate.mjs Outdated Show resolved Hide resolved
polyfill/lib/plaindate.mjs Outdated Show resolved Hide resolved
polyfill/lib/plaindatetime.mjs Outdated Show resolved Hide resolved
polyfill/lib/plainmonthday.mjs Outdated Show resolved Hide resolved
Comment on lines -236 to +238
1. Let _partialTime_ be ? ToTemporalTimeRecord(_temporalTimeLike_, ~partial~).
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Let _partialTime_ be ? ToTemporalTimeRecord(_temporalTimeLike_, ~partial~).
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍
But if this is awkward and options never affects the interpretation of the first argument, then it would also be coherent to move every Set _options_ to ? GetOptionsObject(_options_). to follow full consumption (with constituent validation) of the first argument by PrepareTemporalFields/ToTemporalTimeRecord/etc.—although that is not my preference because it's not clear to me in that case whether GetOptionsObject should precede or follow integration of receiver and argument data in e.g. CalendarMergeFields.

polyfill/lib/plainyearmonth.mjs Outdated Show resolved Hide resolved
1. Let _thisFields_ be ? PrepareTemporalFields(_yearMonth_, _fieldNames_, «»).
1. Perform ! CreateDataPropertyOrThrow(_thisFields_, *"day"*, *1*<sub>𝔽</sub>).
1. Let _thisDate_ be ? CalendarDateFromFields(_calendar_, _thisFields_).
1. Let _otherFields_ be ? PrepareTemporalFields(_other_, _fieldNames_, «»).
1. Perform ! CreateDataPropertyOrThrow(_otherFields_, *"day"*, *1*<sub>𝔽</sub>).
1. Let _otherDate_ be ? CalendarDateFromFields(_calendar_, _otherFields_).
1. Let _untilOptions_ be OrdinaryObjectCreate(*null*).
1. Perform ? CopyDataProperties(_untilOptions_, _settings_.[[Options]], « »).
Copy link
Collaborator

Choose a reason for hiding this comment

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

It is curious that this step can throw; is that a bug in failure to properly consume options earlier on?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't think it's a bug - we have to perform CopyDataProperties on options at some point, so that we can pass an options object to CalendarDateUntil with a modified largestUnit property. options is a user-provided object so it may have accessor properties.

Copy link
Collaborator

@gibson042 gibson042 Jan 17, 2023

Choose a reason for hiding this comment

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

Right, I'm saying that the bug is consuming it so deep in the spec algorithms rather than in initial processing—and in particular in performing CopyDataProperties after GetDifferenceSettings has read several properties on its own.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I could see this going either way - it'd be good to eliminate the duplicate reads, but on the other hand we'd introduce an inconsistency where we'd copy the options object in the since/until methods of PlainDate, PlainDateTime, PlainYearMonth, and ZonedDateTime; and not copy it in the since/until methods of PlainTime and Instant.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Wouldn't options be copied in all since/until methods?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Only the ones where a modified options object needs to be passed on to calendar.dateUntil(). Otherwise, we just read only the needed properties in alphabetical order.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Well, either that serves as explanation of the inconsistency or we'd copy options in all since/until methods even though some technically don't need it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do you have a concrete proposal for this? If we can manage to write that additional change before TC39's review deadline, I wouldn't be opposed to including it here. Otherwise I think it can be done as part of #2289 or left as is.

Copy link
Collaborator

@gibson042 gibson042 Jan 19, 2023

Choose a reason for hiding this comment

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

Concretely, I'm proposing 1. Perform ? CopyDataProperties(_optionsCopy_, _options_, « »). in every DifferenceTemporal<Type> operation immediately after validating other and use of optionsCopy rather than options in every subsequent step. But I'm also comfortable with a compromise in which that change is omitted in DifferenceTemporalInstant and DifferenceTemporalPlainTime, ideally replaced with a NOTE step explaining its omission.

I agree that it is logically part of the fixes for #2289, but will still try to put up a narrow PR since it has been specifically identified (and in fact already has a comment: #2289 (comment) ).

polyfill/lib/zoneddatetime.mjs Outdated Show resolved Hide resolved
spec/zoneddatetime.html Outdated Show resolved Hide resolved
@ptomato ptomato marked this pull request as draft January 17, 2023 19:19
@ptomato
Copy link
Collaborator Author

ptomato commented Jan 17, 2023

Draft until presented at the next TC39 plenary meeting.

ptomato added a commit that referenced this pull request Jan 19, 2023
In ZonedDateTime with(), the 'timeZone' field was observably read from the
receiver and from the object returned from mergeFields(), but never used.
This is not only an unnecessary user call, it becomes a bug when we remove
the ZonedDateTime.p.timeZone property in order to replace it with
.timeZoneId and .getTimeZone().

Also part of #2478
ptomato added a commit that referenced this pull request Jan 21, 2023
In ZonedDateTime with(), the 'timeZone' field was observably read from the
receiver and from the object returned from mergeFields(), but never used.
This is not only an unnecessary user call, it becomes a bug when we remove
the ZonedDateTime.p.timeZone property in order to replace it with
.timeZoneId and .getTimeZone().

Also part of #2478
ptomato added a commit that referenced this pull request Jan 28, 2023
In ZonedDateTime with(), the 'timeZone' field was observably read from the
receiver and from the object returned from mergeFields(), but never used.
This is not only an unnecessary user call, it becomes a bug when we remove
the ZonedDateTime.p.timeZone property in order to replace it with
.timeZoneId and .getTimeZone().

Also part of #2478
ptomato added a commit to ptomato/test262 that referenced this pull request Feb 1, 2023
The with() methods, as well as PlainYearMonth's since() and until(), were
adjusted to read the receiver's fields before the fields of any objects
provided as arguments. This change is observable, so affects several tests
that test the observed order of operations.

Normative PR: tc39/proposal-temporal#2478
ptomato added a commit to ptomato/test262 that referenced this pull request Feb 1, 2023
The with() methods, as well as PlainYearMonth's since() and until(), were
adjusted to read the receiver's fields before the fields of any objects
provided as arguments. This change is observable, so affects several tests
that test the observed order of operations.

Normative PR: tc39/proposal-temporal#2478
ptomato added a commit to tc39/test262 that referenced this pull request Feb 1, 2023
The with() methods, as well as PlainYearMonth's since() and until(), were
adjusted to read the receiver's fields before the fields of any objects
provided as arguments. This change is observable, so affects several tests
that test the observed order of operations.

Normative PR: tc39/proposal-temporal#2478
In ZonedDateTime with(), the 'timeZone' field was observably read from the
receiver and from the object returned from mergeFields(), but never used.
This is an unnecessary user call.
Changes to the order of observable operations in
- PlainDate.p.with
- PlainDateTime.p.with
- PlainMonthDay.p.with
- PlainTime.p.with
- PlainYearMonth.p.since
- PlainYearMonth.p.until
- PlainYearMonth.p.with
- ZonedDateTime.p.with

Swapping the PrepareTemporalFields calls in ZonedDateTime.p.with exposed
another unnecessary user call: the 'timeZone' field was observably read
from the receiver and from the object returned from mergeFields(), but
never used. This is fixed as well.

Closes: #2462
@ptomato ptomato marked this pull request as ready for review February 1, 2023 18:43
@ptomato
Copy link
Collaborator Author

ptomato commented Feb 1, 2023

This change achieved consensus at the 2023-01-31 TC39 plenary meeting. Test262 PR has been merged already.

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.

Receiver should be validated/processed before arguments
2 participants