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

Audit of user code calls, part 2 #2657

Merged
merged 9 commits into from
Sep 13, 2023
Merged

Audit of user code calls, part 2 #2657

merged 9 commits into from
Sep 13, 2023

Conversation

ptomato
Copy link
Collaborator

@ptomato ptomato commented Aug 18, 2023

Following on from #2645: #2519 is a large pull request that touches everything, and it's difficult to keep rebasing it while I work on the test coverage. I'd like to split it into parts, instead, and land each part as soon as the test coverage is ready. This is the second part, which consists of various removals of redundant observable operations. This now has test coverage in tc39/test262#3897.

These commits have already been reviewed in #2519. The changes consist only of rebasing.

Closes: #2247
Closes: #2529

@codecov
Copy link

codecov bot commented Aug 18, 2023

Codecov Report

Patch coverage: 100.00% and project coverage change: +0.12% 🎉

Comparison is base (97baad3) 96.10% compared to head (0455ddf) 96.22%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2657      +/-   ##
==========================================
+ Coverage   96.10%   96.22%   +0.12%     
==========================================
  Files          20       20              
  Lines       11771    11984     +213     
  Branches     2188     2227      +39     
==========================================
+ Hits        11312    11532     +220     
+ Misses        395      389       -6     
+ Partials       64       63       -1     
Files Changed Coverage Δ
polyfill/lib/calendar.mjs 87.18% <100.00%> (+0.04%) ⬆️
polyfill/lib/duration.mjs 95.58% <100.00%> (+0.86%) ⬆️
polyfill/lib/ecmascript.mjs 98.56% <100.00%> (+0.14%) ⬆️
polyfill/lib/plaindatetime.mjs 97.31% <100.00%> (+0.07%) ⬆️
polyfill/lib/zoneddatetime.mjs 100.00% <100.00%> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@ptomato
Copy link
Collaborator Author

ptomato commented Sep 11, 2023

I found one further opportunity to separate ZonedDateTime and PlainDateTime in "Normative: Separate zoned and plain operations in RoundDuration" so I've updated that commit to include it.

@ptomato ptomato force-pushed the user-code-calls-part-2 branch 5 times, most recently from 153c197 to 7765db5 Compare September 12, 2023 19:17
@cjtenny
Copy link
Collaborator

cjtenny commented Sep 12, 2023

FWIW, I took an extensive look at this as part of reviewing tc39/test262#3897 . Found one small bug that Philip's already fixed, and can report that each commit definitely does what it says on the box.

Copy link
Collaborator

@justingrant justingrant left a comment

Choose a reason for hiding this comment

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

Looks good, thanks for doing all this work!

polyfill/lib/ecmascript.mjs Outdated Show resolved Hide resolved
spec/duration.html Outdated Show resolved Hide resolved
spec/duration.html Show resolved Hide resolved
@justingrant
Copy link
Collaborator

Also, shouldn't there be a commit at the end of this PR to update Test262?

@justingrant
Copy link
Collaborator

Also needs a rebase.

If the given rounding options specify a smallest unit of nanoseconds and a
rounding increment of 1, then the rounding operation is a no-op. In that
case, return a copy of the duration, without actually performing the
rounding operation. This applies to all round(), until(), and since()
methods.

In the case of Duration.p.round(), other conditions must be fulfilled as
well for the operation to be a no-op: no balancing must take place.

In the case of Instant.p.round(), PlainDate.p.since(),
PlainDate.p.until(), PlainDateTime.p.round(), PlainDateTime.p.since(),
PlainDateTime.p.until(), PlainTime.p.round(), PlainTime.p.since(),
and PlainTime.p.until(), the change is not observable, so implementors are
free to make this optimization anyway.

This optimization was already the case in PlainDate.p.since/until() and
PlainYearMonth.p.since/until(), so this makes the other since/until()
methods consistent with those.
…uration

relativeTo as a PlainDate is only needed when smallestUnit is year, month,
or week. relativeTo as a ZonedDateTime is used additionally when
smallestUnit is day. However, ToTemporalDate only needs to be called in
the former case. Since ToTemporalDate potentially calls user code,
rearrange some steps to make sure to call it only when necessary.

See: #2247
…mpare

We call UnbalanceDurationRelative twice with the same relativeTo object.
UnbalanceDurationRelative only uses plain or undefined relativeTo, not
zoned, so it will convert it with ToTemporalDate. No need to do this
twice; pre-convert it before the first call.

See: #2247
This converts a ZonedDateTime relativeTo into a PlainDateTime relativeTo
only when necessary, only after potentially throwing other errors, and
only once. Previously, it could be converted up to a few separate times in
each operation, such as UnbalanceDurationRelative, RoundDuration, and
BalanceDurationRelative. Since the conversion is user-visible, we don't
want to perform it when not necessary or perform it more times than
necessary.

Closes: #2247
Closes: #2529
…ds()

When calling CalendarFields with a built-in calendar, previously we would
create a JS Array from the passed List, and pass it to %Temporal.Calendar.
prototype.fields%, which would iterate it observably. So, instead we call
CalendarDateFields when the calendar is a built-in calendar, which doesn't
do anything observable at all.

See: #2289
…Time

There are several places where a ZonedDateTime is converted to a
PlainDateTime, which is a user-visible time zone operation, and then the
same operation is performed again right afterwards in AddZonedDateTime.

Avoid this by making AddZonedDateTime take an optional precalculated
PlainDateTime. If we have it, we can pass it in, and avoid the second
conversion.
ptomato and others added 3 commits September 13, 2023 11:15
If all the fields are equal, then no balancing has to happen, and the
relativeTo point doesn't matter; we know the durations are equal.
CalculateOffsetShift is only used in Duration.compare, when relativeTo is
a ZonedDateTime. Calling it twice performs two ZonedDateTime additions,
which are potentially user-observable method calls. If we are performing
these two additions anyway, we may as well just add each duration to
relativeTo and compare the timestamps. This saves a lot of other
user-observable calls.

It also allows removing the offset-shift parameter from
TotalDurationNanoseconds, because now it is always zero. That parameter
was confusing anyway.
At the same time we remove the days parameter as well, because now there
is no indication that days should only be 24-hour days; we push the
responsibility of deciding whether 24-hour days are appropriate to the
caller.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants