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 3 #2671

Merged
merged 10 commits into from
Oct 4, 2023
78 changes: 59 additions & 19 deletions polyfill/lib/duration.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
SetSlot
} from './slots.mjs';

const MathAbs = Math.abs;
const ObjectCreate = Object.create;

export class Duration {
Expand Down Expand Up @@ -288,8 +289,12 @@ export class Duration {
const balancingRequested = largestUnit !== existingLargestUnit;
const calendarUnitsPresent = years !== 0 || months !== 0 || weeks !== 0;
const timeUnitsOverflowWillOccur =
minutes >= 60 || seconds >= 60 || milliseconds >= 1000 || microseconds >= 1000 || nanoseconds >= 1000;
const hoursToDaysConversionMayOccur = (days !== 0 && zonedRelativeTo) || hours >= 24;
MathAbs(minutes) >= 60 ||
MathAbs(seconds) >= 60 ||
MathAbs(milliseconds) >= 1000 ||
MathAbs(microseconds) >= 1000 ||
MathAbs(nanoseconds) >= 1000;
const hoursToDaysConversionMayOccur = (days !== 0 && zonedRelativeTo) || MathAbs(hours) >= 24;
if (
roundingGranularityIsNoop &&
!balancingRequested &&
Expand All @@ -300,18 +305,29 @@ export class Duration {
return new Duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
}

const plainRelativeToWillBeUsed =
let precalculatedPlainDateTime;
const plainDateTimeOrRelativeToWillBeUsed =
!roundingGranularityIsNoop ||
largestUnit === 'year' ||
largestUnit === 'month' ||
largestUnit === 'week' ||
largestUnit === 'day' ||
smallestUnit === 'year' ||
smallestUnit === 'month' ||
smallestUnit === 'week' ||
years !== 0 ||
months !== 0 ||
weeks !== 0 ||
smallestUnit === 'day' ||
calendarUnitsPresent ||
days !== 0;
if (zonedRelativeTo && plainRelativeToWillBeUsed) {
// Convert a ZonedDateTime relativeTo to PlainDate only if needed in one
// of the operations below, because the conversion is user visible
plainRelativeTo = ES.ToTemporalDate(zonedRelativeTo);
if (zonedRelativeTo && plainDateTimeOrRelativeToWillBeUsed) {
// Convert a ZonedDateTime relativeTo to PlainDateTime and PlainDate only
// if either is needed in one of the operations below, because the
// conversion is user visible
precalculatedPlainDateTime = ES.GetPlainDateTimeFor(
GetSlot(zonedRelativeTo, TIME_ZONE),
GetSlot(zonedRelativeTo, INSTANT),
GetSlot(zonedRelativeTo, CALENDAR)
);
plainRelativeTo = ES.TemporalDateTimeToDate(precalculatedPlainDateTime);
}

({ years, months, weeks, days } = ES.UnbalanceDateDurationRelative(
Expand All @@ -338,7 +354,8 @@ export class Duration {
smallestUnit,
roundingMode,
plainRelativeTo,
zonedRelativeTo
zonedRelativeTo,
precalculatedPlainDateTime
));
if (zonedRelativeTo) {
({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } =
Expand All @@ -356,7 +373,8 @@ export class Duration {
roundingIncrement,
smallestUnit,
roundingMode,
zonedRelativeTo
zonedRelativeTo,
precalculatedPlainDateTime
));
({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceTimeDurationRelative(
days,
Expand All @@ -367,7 +385,8 @@ export class Duration {
microseconds,
nanoseconds,
largestUnit,
zonedRelativeTo
zonedRelativeTo,
precalculatedPlainDateTime
));
} else {
({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceTimeDuration(
Expand Down Expand Up @@ -416,12 +435,25 @@ export class Duration {
let { plainRelativeTo, zonedRelativeTo } = ES.ToRelativeTemporalObject(totalOf);
const unit = ES.GetTemporalUnit(totalOf, 'unit', 'datetime', ES.REQUIRED);

const plainRelativeToWillBeUsed =
unit === 'year' || unit === 'month' || unit === 'week' || years !== 0 || months !== 0 || weeks !== 0;
if (zonedRelativeTo !== undefined && plainRelativeToWillBeUsed) {
let precalculatedPlainDateTime;
const plainDateTimeOrRelativeToWillBeUsed =
unit === 'year' ||
unit === 'month' ||
unit === 'week' ||
unit === 'day' ||
years !== 0 ||
months !== 0 ||
weeks !== 0 ||
days !== 0;
if (zonedRelativeTo && plainDateTimeOrRelativeToWillBeUsed) {
// Convert a ZonedDateTime relativeTo to PlainDate only if needed in one
// of the operations below, because the conversion is user visible
plainRelativeTo = ES.ToTemporalDate(zonedRelativeTo);
precalculatedPlainDateTime = ES.GetPlainDateTimeFor(
GetSlot(zonedRelativeTo, TIME_ZONE),
GetSlot(zonedRelativeTo, INSTANT),
GetSlot(zonedRelativeTo, CALENDAR)
);
plainRelativeTo = ES.TemporalDateTimeToDate(precalculatedPlainDateTime);
}

// Convert larger units down to days
Expand All @@ -436,7 +468,14 @@ export class Duration {
// If the unit we're totalling is smaller than `days`, convert days down to that unit.
let balanceResult;
if (zonedRelativeTo) {
const intermediate = ES.MoveRelativeZonedDateTime(zonedRelativeTo, years, months, weeks, 0);
const intermediate = ES.MoveRelativeZonedDateTime(
zonedRelativeTo,
years,
months,
weeks,
0,
precalculatedPlainDateTime
);
balanceResult = ES.BalancePossiblyInfiniteTimeDurationRelative(
days,
hours,
Expand Down Expand Up @@ -482,7 +521,8 @@ export class Duration {
unit,
'trunc',
plainRelativeTo,
zonedRelativeTo
zonedRelativeTo,
precalculatedPlainDateTime
);
return total;
}
Expand Down
Loading