Skip to content

Commit

Permalink
Implement PlainDate string methods (#4119)
Browse files Browse the repository at this point in the history
* Bump temporal_rs and add Date string methods

* Add zdt handling in to_instant op

* Cargo fmt

* Fix failing test output
  • Loading branch information
nekevss authored Jan 12, 2025
1 parent cf2aa58 commit efcafda
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 24 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ intrusive-collections = "0.9.7"
cfg-if = "1.0.0"
either = "1.13.0"
sys-locale = "0.3.2"
temporal_rs = { git = "https://github.com/boa-dev/temporal.git", rev = "8b796edec18a2652af282735aab4a2d0512b9a1d", features = ["tzdb", "now"] }
temporal_rs = { git = "https://github.com/boa-dev/temporal.git", rev = "436b07d9b27e3e2274905c9a4eabf8bbff9ad9ec", features = ["tzdb"] }
web-time = "1.1.0"
criterion = "0.5.1"
float-cmp = "0.10.0"
Expand Down
6 changes: 2 additions & 4 deletions core/engine/src/builtins/temporal/instant/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,10 +531,8 @@ fn to_temporal_instant(item: &JsValue, context: &mut Context) -> JsResult<InnerI
// d. Set item to ? ToPrimitive(item, string).
if let Some(instant) = obj.downcast_ref::<Instant>() {
return Ok(instant.inner);
} else if let Some(_zdt) = obj.downcast_ref::<ZonedDateTime>() {
return Err(JsNativeError::error()
.with_message("Not yet implemented.")
.into());
} else if let Some(zdt) = obj.downcast_ref::<ZonedDateTime>() {
return Ok(zdt.inner.to_instant());
}
item.to_primitive(context, PreferredType::String)?
} else {
Expand Down
4 changes: 2 additions & 2 deletions core/engine/src/builtins/temporal/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
js_string, Context, JsNativeError, JsObject, JsResult, JsString, JsValue,
};
use temporal_rs::options::{
ArithmeticOverflow, CalendarName, DifferenceSettings, Disambiguation, DurationOverflow,
ArithmeticOverflow, DifferenceSettings, Disambiguation, DisplayCalendar, DurationOverflow,
OffsetDisambiguation, RoundingIncrement, TemporalRoundingMode, TemporalUnit,
};

Expand Down Expand Up @@ -116,7 +116,7 @@ impl ParsableOptionType for DurationOverflow {}
impl ParsableOptionType for Disambiguation {}
impl ParsableOptionType for OffsetDisambiguation {}
impl ParsableOptionType for TemporalRoundingMode {}
impl ParsableOptionType for CalendarName {}
impl ParsableOptionType for DisplayCalendar {}

impl OptionType for RoundingIncrement {
fn from_value(value: JsValue, context: &mut Context) -> JsResult<Self> {
Expand Down
35 changes: 34 additions & 1 deletion core/engine/src/builtins/temporal/plain_date/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use crate::{
use boa_gc::{Finalize, Trace};
use boa_profiler::Profiler;
use temporal_rs::{
options::ArithmeticOverflow, partial::PartialDate, PlainDate as InnerDate, TinyAsciiStr,
options::{ArithmeticOverflow, DisplayCalendar},
partial::PartialDate,
PlainDate as InnerDate, TinyAsciiStr,
};

use super::{
Expand Down Expand Up @@ -214,6 +216,8 @@ impl IntrinsicObject for PlainDate {
.method(Self::since, js_string!("since"), 1)
.method(Self::equals, js_string!("equals"), 1)
.method(Self::to_plain_datetime, js_string!("toPlainDateTime"), 0)
.method(Self::to_string, js_string!("toString"), 0)
.method(Self::to_json, js_string!("toJSON"), 0)
.method(Self::value_of, js_string!("valueOf"), 0)
.build();
}
Expand Down Expand Up @@ -730,6 +734,35 @@ impl PlainDate {
create_temporal_datetime(date.inner.to_date_time(time)?, None, context).map(Into::into)
}

/// 3.3.30 `Temporal.PlainDate.prototype.toString ( [ options ] )`
fn to_string(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
let date = this
.as_object()
.and_then(JsObject::downcast_ref::<Self>)
.ok_or_else(|| {
JsNativeError::typ().with_message("the this object must be a PlainDate object.")
})?;

let options = get_options_object(args.get_or_undefined(0))?;
let display_calendar =
get_option::<DisplayCalendar>(&options, js_string!("calendarName"), context)?
.unwrap_or(DisplayCalendar::Auto);
Ok(JsString::from(date.inner.to_ixdtf_string(display_calendar)).into())
}

// 3.3.32 `Temporal.PlainDate.prototype.toJSON ( )`
fn to_json(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
let date = this
.as_object()
.and_then(JsObject::downcast_ref::<Self>)
.ok_or_else(|| {
JsNativeError::typ().with_message("the this object must be a PlainDate object.")
})?;

Ok(JsString::from(date.inner.to_string()).into())
}

/// 3.3.33 `Temporal.PlainDate.prototype.valueOf ( )`
pub(crate) fn value_of(_this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
Err(JsNativeError::typ()
.with_message("`valueOf` not supported by Temporal built-ins. See 'compare', 'equals', or `toString`")
Expand Down
2 changes: 1 addition & 1 deletion core/engine/src/builtins/temporal/plain_date/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ fn string_null_option_value() {
run_test_actions([TestAction::assert_native_error(
"Temporal.PlainDate.from('1976-11-18Z', null)",
JsNativeErrorKind::Range,
"Error: Unexpected character found after parsing was completed.",
"RangeError: Unexpected character found after parsing was completed.",
)]);
}
14 changes: 7 additions & 7 deletions core/engine/src/builtins/temporal/plain_month_day/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use boa_gc::{Finalize, Trace};
use boa_profiler::Profiler;

use temporal_rs::{
options::{ArithmeticOverflow, CalendarName},
options::{ArithmeticOverflow, DisplayCalendar},
partial::PartialDate,
PlainMonthDay as InnerMonthDay, TinyAsciiStr,
};
Expand Down Expand Up @@ -110,8 +110,8 @@ impl PlainMonthDay {
// 4. Let showCalendar be ? ToShowCalendarOption(options).
// Get calendarName from the options object
let show_calendar =
get_option::<CalendarName>(&options, js_string!("calendarName"), context)?
.unwrap_or(CalendarName::Auto);
get_option::<DisplayCalendar>(&options, js_string!("calendarName"), context)?
.unwrap_or(DisplayCalendar::Auto);

Ok(month_day_to_string(inner, show_calendar))
}
Expand Down Expand Up @@ -231,7 +231,7 @@ impl BuiltInConstructor for PlainMonthDay {

// ==== `PlainMonthDay` Abstract Operations ====

fn month_day_to_string(inner: &InnerMonthDay, show_calendar: CalendarName) -> JsValue {
fn month_day_to_string(inner: &InnerMonthDay, show_calendar: DisplayCalendar) -> JsValue {
// Let month be monthDay.[[ISOMonth]] formatted as a two-digit decimal number, padded to the left with a zero if necessary
let month = inner.iso_month().to_string();

Expand All @@ -252,11 +252,11 @@ fn month_day_to_string(inner: &InnerMonthDay, show_calendar: CalendarName) -> Js
// b. Set result to the string-concatenation of result, the code unit 0x0040 (COMMERCIAL AT), and calendarString.
if (matches!(
show_calendar,
CalendarName::Critical | CalendarName::Always | CalendarName::Auto
)) && !(matches!(show_calendar, CalendarName::Auto) && calendar_id == "iso8601")
DisplayCalendar::Critical | DisplayCalendar::Always | DisplayCalendar::Auto
)) && !(matches!(show_calendar, DisplayCalendar::Auto) && calendar_id == "iso8601")
{
let year = inner.iso_year().to_string();
let flag = if matches!(show_calendar, CalendarName::Critical) {
let flag = if matches!(show_calendar, DisplayCalendar::Critical) {
"!"
} else {
""
Expand Down
14 changes: 7 additions & 7 deletions core/engine/src/builtins/temporal/plain_year_month/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use boa_gc::{Finalize, Trace};
use boa_profiler::Profiler;

use temporal_rs::{
options::{ArithmeticOverflow, CalendarName},
options::{ArithmeticOverflow, DisplayCalendar},
Duration, PlainYearMonth as InnerYearMonth,
};

Expand Down Expand Up @@ -433,8 +433,8 @@ impl PlainYearMonth {
// 4. Let showCalendar be ? ToShowCalendarOption(options).
// Get calendarName from the options object
let show_calendar =
get_option::<CalendarName>(&options, js_string!("calendarName"), context)?
.unwrap_or(CalendarName::Auto);
get_option::<DisplayCalendar>(&options, js_string!("calendarName"), context)?
.unwrap_or(DisplayCalendar::Auto);

Ok(year_month_to_string(inner, show_calendar))
}
Expand Down Expand Up @@ -529,7 +529,7 @@ fn add_or_subtract_duration(
create_temporal_year_month(year_month_result, None, context)
}

fn year_month_to_string(inner: &InnerYearMonth, show_calendar: CalendarName) -> JsValue {
fn year_month_to_string(inner: &InnerYearMonth, show_calendar: DisplayCalendar) -> JsValue {
// Let year be PadISOYear(yearMonth.[[ISOYear]]).
let year = inner.padded_iso_year_string();
// Let month be ToZeroPaddedDecimalString(yearMonth.[[ISOMonth]], 2).
Expand All @@ -545,12 +545,12 @@ fn year_month_to_string(inner: &InnerYearMonth, show_calendar: CalendarName) ->
// 7. Set result to the string-concatenation of result and calendarString.
if matches!(
show_calendar,
CalendarName::Critical | CalendarName::Always | CalendarName::Auto
) && !(matches!(show_calendar, CalendarName::Auto) && inner.calendar_id() == "iso8601")
DisplayCalendar::Critical | DisplayCalendar::Always | DisplayCalendar::Auto
) && !(matches!(show_calendar, DisplayCalendar::Auto) && inner.calendar_id() == "iso8601")
{
let calendar = inner.calendar_id();
let calendar_string = calendar.to_string();
let flag = if matches!(show_calendar, CalendarName::Critical) {
let flag = if matches!(show_calendar, DisplayCalendar::Critical) {
"!"
} else {
""
Expand Down

0 comments on commit efcafda

Please sign in to comment.