diff --git a/boa_engine/Cargo.toml b/boa_engine/Cargo.toml index a9cb58f670d..a93f8ee755c 100644 --- a/boa_engine/Cargo.toml +++ b/boa_engine/Cargo.toml @@ -62,7 +62,7 @@ boa_profiler.workspace = true boa_macros.workspace = true boa_ast.workspace = true boa_parser.workspace = true -boa_temporal = { workspace = true, features = ["context"] } +boa_temporal = { workspace = true } serde = { workspace = true, features = ["derive", "rc"] } serde_json.workspace = true rand = "0.8.5" diff --git a/boa_engine/src/builtins/temporal/calendar/object.rs b/boa_engine/src/builtins/temporal/calendar/object.rs index f09ef1158fa..291a3d59257 100644 --- a/boa_engine/src/builtins/temporal/calendar/object.rs +++ b/boa_engine/src/builtins/temporal/calendar/object.rs @@ -17,7 +17,7 @@ use boa_temporal::{ month_day::MonthDay, options::ArithmeticOverflow, year_month::YearMonth, - TemporalResult, TinyStr4, TinyStr8, + TemporalResult, TinyAsciiStr, }; use num_traits::ToPrimitive; @@ -222,7 +222,11 @@ impl CalendarProtocol for CustomRuntimeCalendar { Err(TemporalError::general("Not yet implemented.")) } - fn era(&self, _: &CalendarDateLike, _: &mut dyn Any) -> TemporalResult> { + fn era( + &self, + _: &CalendarDateLike, + _: &mut dyn Any, + ) -> TemporalResult>> { // Return undefined as custom calendars do not implement -> Currently. Ok(None) } @@ -322,7 +326,7 @@ impl CalendarProtocol for CustomRuntimeCalendar { &self, date_like: &CalendarDateLike, context: &mut dyn Any, - ) -> TemporalResult { + ) -> TemporalResult> { let context = context .downcast_mut::() .expect("Context was not provided for a CustomCalendar."); @@ -344,7 +348,7 @@ impl CalendarProtocol for CustomRuntimeCalendar { return Err(TemporalError::r#type().with_message("monthCode return must be a String.")); }; - let result = TinyStr4::from_str(&result.to_std_string_escaped()) + let result = TinyAsciiStr::<4>::from_str(&result.to_std_string_escaped()) .map_err(|_| TemporalError::general("Unexpected monthCode value."))?; Ok(result) diff --git a/boa_temporal/Cargo.toml b/boa_temporal/Cargo.toml index 058e64d3490..2c3a1286209 100644 --- a/boa_temporal/Cargo.toml +++ b/boa_temporal/Cargo.toml @@ -19,8 +19,5 @@ num-bigint = { workspace = true, features = ["serde"] } bitflags.workspace = true num-traits.workspace = true -[features] -context = [] - [lints] workspace = true diff --git a/boa_temporal/src/calendar.rs b/boa_temporal/src/calendar.rs index 1348e8d0ce9..5d9e112f830 100644 --- a/boa_temporal/src/calendar.rs +++ b/boa_temporal/src/calendar.rs @@ -22,7 +22,7 @@ use crate::{ TemporalError, TemporalResult, }; -use tinystr::{TinyStr4, TinyStr8}; +use tinystr::TinyAsciiStr; use self::iso::IsoCalendar; @@ -200,7 +200,7 @@ pub trait CalendarProtocol: CalendarProtocolClone { &self, date_like: &CalendarDateLike, context: &mut dyn Any, - ) -> TemporalResult>; + ) -> TemporalResult>>; /// Returns the era year for a given `temporaldatelike` fn era_year( &self, @@ -217,7 +217,7 @@ pub trait CalendarProtocol: CalendarProtocolClone { &self, date_like: &CalendarDateLike, context: &mut dyn Any, - ) -> TemporalResult; + ) -> TemporalResult>; /// Returns the `day` for a given `temporaldatelike` fn day(&self, date_like: &CalendarDateLike, context: &mut dyn Any) -> TemporalResult; /// Returns a value representing the day of the week for a date. @@ -401,7 +401,7 @@ impl CalendarSlot { &self, date_like: &CalendarDateLike, context: &mut dyn Any, - ) -> TemporalResult { + ) -> TemporalResult> { match self { Self::Identifier(id) => { let protocol = AvailableCalendars::from_str(id)?.to_protocol(); diff --git a/boa_temporal/src/calendar/iso.rs b/boa_temporal/src/calendar/iso.rs index 7ddb835e3e2..1ac7283fb22 100644 --- a/boa_temporal/src/calendar/iso.rs +++ b/boa_temporal/src/calendar/iso.rs @@ -13,7 +13,7 @@ use crate::{ }; use std::any::Any; -use tinystr::{TinyStr4, TinyStr8}; +use tinystr::TinyAsciiStr; use super::{CalendarDateLike, CalendarFieldsType, CalendarProtocol, CalendarSlot}; @@ -132,7 +132,11 @@ impl CalendarProtocol for IsoCalendar { } /// `Temporal.Calendar.prototype.era( dateLike )` for iso8601 calendar. - fn era(&self, _: &CalendarDateLike, _: &mut dyn Any) -> TemporalResult> { + fn era( + &self, + _: &CalendarDateLike, + _: &mut dyn Any, + ) -> TemporalResult>> { // Returns undefined on iso8601. Ok(None) } @@ -158,7 +162,7 @@ impl CalendarProtocol for IsoCalendar { &self, date_like: &CalendarDateLike, _: &mut dyn Any, - ) -> TemporalResult { + ) -> TemporalResult> { let date = date_like.as_iso_date().as_icu4x()?; Ok(date.month().code.0) } diff --git a/boa_temporal/src/date.rs b/boa_temporal/src/date.rs index 8413d5ca91c..054940790c4 100644 --- a/boa_temporal/src/date.rs +++ b/boa_temporal/src/date.rs @@ -27,68 +27,6 @@ impl Date { Self { iso, calendar } } - #[inline] - /// `DifferenceDate` - pub(crate) fn diff_date( - &self, - other: &Self, - largest_unit: TemporalUnit, - context: &mut dyn Any, - ) -> TemporalResult { - if self.iso.year() == other.iso.year() - && self.iso.month() == other.iso.month() - && self.iso.day() == other.iso.day() - { - return Ok(Duration::default()); - } - - if largest_unit == TemporalUnit::Day { - let days = self.days_until(other); - return Ok(Duration::from_date_duration(DateDuration::new( - 0f64, - 0f64, - 0f64, - f64::from(days), - ))); - } - - self.calendar() - .date_until(self, other, largest_unit, context) - } - - #[inline] - /// Internal `AddDate` function - pub(crate) fn add_date( - &self, - duration: &Duration, - overflow: ArithmeticOverflow, - context: &mut dyn Any, - ) -> TemporalResult { - // 1. If options is not present, set options to undefined. - // 2. If duration.[[Years]] ≠ 0, or duration.[[Months]] ≠ 0, or duration.[[Weeks]] ≠ 0, then - if duration.date().years() != 0.0 - || duration.date().months() != 0.0 - || duration.date().weeks() != 0.0 - { - // a. If dateAdd is not present, then - // i. Set dateAdd to unused. - // ii. If calendar is an Object, set dateAdd to ? GetMethod(calendar, "dateAdd"). - // b. Return ? CalendarDateAdd(calendar, plainDate, duration, options, dateAdd). - return self.calendar().date_add(self, duration, overflow, context); - } - - // 3. Let overflow be ? ToTemporalOverflow(options). - // 4. Let days be ? BalanceTimeDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day").[[Days]]. - let (days, _) = duration.balance_time_duration(TemporalUnit::Day)?; - - // 5. Let result be ? AddISODate(plainDate.[[ISOYear]], plainDate.[[ISOMonth]], plainDate.[[ISODay]], 0, 0, 0, days, overflow). - let result = self - .iso - .add_iso_date(&DateDuration::new(0f64, 0f64, 0f64, days), overflow)?; - - Ok(Self::new_unchecked(result, self.calendar().clone())) - } - #[inline] /// Returns a new moved date and the days associated with that adjustment pub(crate) fn move_relative_date( @@ -96,7 +34,8 @@ impl Date { duration: &Duration, context: &mut dyn Any, ) -> TemporalResult<(Self, f64)> { - let new_date = self.add_date(duration, ArithmeticOverflow::Constrain, context)?; + let new_date = + self.contextual_add_date(duration, ArithmeticOverflow::Constrain, context)?; let days = f64::from(self.days_until(&new_date)); Ok((new_date, days)) } @@ -189,57 +128,93 @@ impl IsoDateSlots for Date { // ==== Context based API ==== impl Date { - /// Returns the date after adding the given duration to date. + /// Returns the date after adding the given duration to date with a provided context. /// /// Temporal Equivalent: 3.5.13 `AddDate ( calendar, plainDate, duration [ , options [ , dateAdd ] ] )` #[inline] - #[cfg(feature = "context")] - pub fn add_to_date( + pub fn contextual_add_date( &self, duration: &Duration, overflow: ArithmeticOverflow, context: &mut dyn Any, ) -> TemporalResult { - self.add_date(duration, overflow, context) + // 1. If options is not present, set options to undefined. + // 2. If duration.[[Years]] ≠ 0, or duration.[[Months]] ≠ 0, or duration.[[Weeks]] ≠ 0, then + if duration.date().years() != 0.0 + || duration.date().months() != 0.0 + || duration.date().weeks() != 0.0 + { + // a. If dateAdd is not present, then + // i. Set dateAdd to unused. + // ii. If calendar is an Object, set dateAdd to ? GetMethod(calendar, "dateAdd"). + // b. Return ? CalendarDateAdd(calendar, plainDate, duration, options, dateAdd). + return self.calendar().date_add(self, duration, overflow, context); + } + + // 3. Let overflow be ? ToTemporalOverflow(options). + // 4. Let days be ? BalanceTimeDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day").[[Days]]. + let (days, _) = duration.balance_time_duration(TemporalUnit::Day)?; + + // 5. Let result be ? AddISODate(plainDate.[[ISOYear]], plainDate.[[ISOMonth]], plainDate.[[ISODay]], 0, 0, 0, days, overflow). + let result = self + .iso + .add_iso_date(&DateDuration::new(0f64, 0f64, 0f64, days), overflow)?; + + Ok(Self::new_unchecked(result, self.calendar().clone())) } /// Returns the date after adding the given duration to date. /// /// Temporal Equivalent: 3.5.13 `AddDate ( calendar, plainDate, duration [ , options [ , dateAdd ] ] )` #[inline] - #[cfg(not(feature = "context"))] - pub fn add_to_date( + pub fn add_date( &self, duration: &Duration, overflow: ArithmeticOverflow, ) -> TemporalResult { - self.add_date(duration, overflow, &mut ()) + self.contextual_add_date(duration, overflow, &mut ()) } - /// Returns a duration representing the difference between the dates one and two. + /// Returns a duration representing the difference between the dates one and two with a provided context. /// /// Temporal Equivalent: 3.5.6 `DifferenceDate ( calendar, one, two, options )` #[inline] - #[cfg(feature = "context")] - pub fn difference_date( + pub fn contextual_difference_date( &self, other: &Self, largest_unit: TemporalUnit, context: &mut dyn Any, ) -> TemporalResult { - self.diff_date(other, largest_unit, context) + if self.iso.year() == other.iso.year() + && self.iso.month() == other.iso.month() + && self.iso.day() == other.iso.day() + { + return Ok(Duration::default()); + } + + if largest_unit == TemporalUnit::Day { + let days = self.days_until(other); + return Ok(Duration::from_date_duration(DateDuration::new( + 0f64, + 0f64, + 0f64, + f64::from(days), + ))); + } + + self.calendar() + .date_until(self, other, largest_unit, context) } /// Returns a duration representing the difference between the dates one and two. /// /// Temporal Equivalent: 3.5.6 `DifferenceDate ( calendar, one, two, options )` #[inline] - #[cfg(not(feature = "context"))] pub fn difference_date( &self, other: &Self, largest_unit: TemporalUnit, ) -> TemporalResult { - self.diff_date(other, largest_unit, &mut ()) + self.contextual_difference_date(other, largest_unit, &mut ()) } } diff --git a/boa_temporal/src/duration.rs b/boa_temporal/src/duration.rs index e04f7cfd7b4..fa2c9f4962b 100644 --- a/boa_temporal/src/duration.rs +++ b/boa_temporal/src/duration.rs @@ -1245,7 +1245,7 @@ impl Duration { // i. Let dateAdd be unused. // e. Let yearsLater be ? AddDate(calendar, plainRelativeTo, yearsDuration, undefined, dateAdd). - let years_later = plain_relative_to.add_date( + let years_later = plain_relative_to.contextual_add_date( &years_duration, ArithmeticOverflow::Constrain, context, @@ -1263,7 +1263,7 @@ impl Duration { ); // g. Let yearsMonthsWeeksLater be ? AddDate(calendar, plainRelativeTo, yearsMonthsWeeks, undefined, dateAdd). - let years_months_weeks_later = plain_relative_to.add_date( + let years_months_weeks_later = plain_relative_to.contextual_add_date( &years_months_weeks, ArithmeticOverflow::Constrain, context, @@ -1290,8 +1290,11 @@ impl Duration { // m. Let untilOptions be OrdinaryObjectCreate(null). // n. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "year"). // o. Let timePassed be ? DifferenceDate(calendar, plainRelativeTo, wholeDaysLater, untilOptions). - let time_passed = - plain_relative_to.diff_date(&whole_days_later, TemporalUnit::Year, context)?; + let time_passed = plain_relative_to.contextual_difference_date( + &whole_days_later, + TemporalUnit::Year, + context, + )?; // p. Let yearsPassed be timePassed.[[Years]]. let years_passed = time_passed.date.years(); @@ -1358,7 +1361,7 @@ impl Duration { // i. Let dateAdd be unused. // e. Let yearsMonthsLater be ? AddDate(calendar, plainRelativeTo, yearsMonths, undefined, dateAdd). - let years_months_later = plain_relative_to.add_date( + let years_months_later = plain_relative_to.contextual_add_date( &years_months, ArithmeticOverflow::Constrain, context, @@ -1373,7 +1376,7 @@ impl Duration { )); // g. Let yearsMonthsWeeksLater be ? AddDate(calendar, plainRelativeTo, yearsMonthsWeeks, undefined, dateAdd). - let years_months_weeks_later = plain_relative_to.add_date( + let years_months_weeks_later = plain_relative_to.contextual_add_date( &years_months_weeks, ArithmeticOverflow::Constrain, context, diff --git a/boa_temporal/src/fields.rs b/boa_temporal/src/fields.rs index 98ae9d0bad8..1c6d2a94118 100644 --- a/boa_temporal/src/fields.rs +++ b/boa_temporal/src/fields.rs @@ -6,7 +6,7 @@ use crate::{error::TemporalError, TemporalResult}; use bitflags::bitflags; // use rustc_hash::FxHashSet; -use tinystr::{TinyStr16, TinyStr4}; +use tinystr::{TinyAsciiStr, TinyStr16, TinyStr4}; bitflags! { /// FieldMap maps the currently active fields on the `TemporalField` @@ -467,7 +467,7 @@ impl TemporalFields { } } -fn month_code_to_integer(mc: TinyStr4) -> TemporalResult { +fn month_code_to_integer(mc: TinyAsciiStr<4>) -> TemporalResult { match mc.as_str() { "M01" => Ok(1), "M02" => Ok(2), diff --git a/boa_temporal/src/lib.rs b/boa_temporal/src/lib.rs index e2da7ee6825..fb5149aac07 100644 --- a/boa_temporal/src/lib.rs +++ b/boa_temporal/src/lib.rs @@ -43,7 +43,7 @@ pub mod zoneddatetime; // TODO: evaluate positives and negatives of using tinystr. // Re-exporting tinystr as a convenience, as it is currently tied into the API. -pub use tinystr::{TinyAsciiStr, TinyStr16, TinyStr4, TinyStr8}; +pub use tinystr::TinyAsciiStr; pub use error::TemporalError;