diff --git a/Cargo.lock b/Cargo.lock index d91d84fa0a8..67eda682304 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3541,7 +3541,7 @@ checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078" [[package]] name = "temporal_rs" version = "0.0.4" -source = "git+https://github.com/boa-dev/temporal.git?rev=8b796edec18a2652af282735aab4a2d0512b9a1d#8b796edec18a2652af282735aab4a2d0512b9a1d" +source = "git+https://github.com/boa-dev/temporal.git?rev=436b07d9b27e3e2274905c9a4eabf8bbff9ad9ec#436b07d9b27e3e2274905c9a4eabf8bbff9ad9ec" dependencies = [ "bitflags 2.6.0", "combine", @@ -3554,6 +3554,7 @@ dependencies = [ "tinystr 0.8.0", "tzif", "web-time", + "writeable 0.6.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b411f795297..951f1f0f9a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/core/engine/src/builtins/temporal/instant/mod.rs b/core/engine/src/builtins/temporal/instant/mod.rs index 366fe7bcfe9..5177673d17a 100644 --- a/core/engine/src/builtins/temporal/instant/mod.rs +++ b/core/engine/src/builtins/temporal/instant/mod.rs @@ -531,10 +531,8 @@ fn to_temporal_instant(item: &JsValue, context: &mut Context) -> JsResult() { return Ok(instant.inner); - } else if let Some(_zdt) = obj.downcast_ref::() { - return Err(JsNativeError::error() - .with_message("Not yet implemented.") - .into()); + } else if let Some(zdt) = obj.downcast_ref::() { + return Ok(zdt.inner.to_instant()); } item.to_primitive(context, PreferredType::String)? } else { diff --git a/core/engine/src/builtins/temporal/options.rs b/core/engine/src/builtins/temporal/options.rs index 46883c52eeb..3213435bbab 100644 --- a/core/engine/src/builtins/temporal/options.rs +++ b/core/engine/src/builtins/temporal/options.rs @@ -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, }; @@ -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 { diff --git a/core/engine/src/builtins/temporal/plain_date/mod.rs b/core/engine/src/builtins/temporal/plain_date/mod.rs index a173a320c74..a008fb98217 100644 --- a/core/engine/src/builtins/temporal/plain_date/mod.rs +++ b/core/engine/src/builtins/temporal/plain_date/mod.rs @@ -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::{ @@ -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(); } @@ -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 { + let date = this + .as_object() + .and_then(JsObject::downcast_ref::) + .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::(&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 { + let date = this + .as_object() + .and_then(JsObject::downcast_ref::) + .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 { Err(JsNativeError::typ() .with_message("`valueOf` not supported by Temporal built-ins. See 'compare', 'equals', or `toString`") diff --git a/core/engine/src/builtins/temporal/plain_date/tests.rs b/core/engine/src/builtins/temporal/plain_date/tests.rs index d98f5313e89..f492a3d61c1 100644 --- a/core/engine/src/builtins/temporal/plain_date/tests.rs +++ b/core/engine/src/builtins/temporal/plain_date/tests.rs @@ -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.", )]); } diff --git a/core/engine/src/builtins/temporal/plain_month_day/mod.rs b/core/engine/src/builtins/temporal/plain_month_day/mod.rs index 26f20b203b0..8030d1cf07a 100644 --- a/core/engine/src/builtins/temporal/plain_month_day/mod.rs +++ b/core/engine/src/builtins/temporal/plain_month_day/mod.rs @@ -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, }; @@ -110,8 +110,8 @@ impl PlainMonthDay { // 4. Let showCalendar be ? ToShowCalendarOption(options). // Get calendarName from the options object let show_calendar = - get_option::(&options, js_string!("calendarName"), context)? - .unwrap_or(CalendarName::Auto); + get_option::(&options, js_string!("calendarName"), context)? + .unwrap_or(DisplayCalendar::Auto); Ok(month_day_to_string(inner, show_calendar)) } @@ -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(); @@ -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 { "" diff --git a/core/engine/src/builtins/temporal/plain_year_month/mod.rs b/core/engine/src/builtins/temporal/plain_year_month/mod.rs index 389858c044b..b06cbfa1403 100644 --- a/core/engine/src/builtins/temporal/plain_year_month/mod.rs +++ b/core/engine/src/builtins/temporal/plain_year_month/mod.rs @@ -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, }; @@ -433,8 +433,8 @@ impl PlainYearMonth { // 4. Let showCalendar be ? ToShowCalendarOption(options). // Get calendarName from the options object let show_calendar = - get_option::(&options, js_string!("calendarName"), context)? - .unwrap_or(CalendarName::Auto); + get_option::(&options, js_string!("calendarName"), context)? + .unwrap_or(DisplayCalendar::Auto); Ok(year_month_to_string(inner, show_calendar)) } @@ -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). @@ -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 { ""