Skip to content

Commit

Permalink
Bump temporal_rs and adjust Now for recent changes (#4162)
Browse files Browse the repository at this point in the history
  • Loading branch information
nekevss authored Feb 16, 2025
1 parent 81ab11f commit a8aea9c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 39 deletions.
4 changes: 2 additions & 2 deletions 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 @@ -113,7 +113,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 = "50003f04706406654e695c68e54d12c471851421", features = ["tzdb"] }
temporal_rs = { git = "https://github.com/boa-dev/temporal.git", rev = "6a3c74fbf20a870bacccdcd6b11d8c0d4dd459d8", default-features = false, features = ["tzdb"] }
web-time = "1.1.0"
criterion = "0.5.1"
float-cmp = "0.10.0"
Expand Down
3 changes: 2 additions & 1 deletion core/engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ trace = ["js"]
annex-b = ["boa_ast/annex-b", "boa_parser/annex-b"]

# Enable Boa's Temporal proposal implementation
temporal = ["dep:icu_calendar", "dep:temporal_rs"]
temporal = ["dep:icu_calendar", "dep:temporal_rs", "dep:iana-time-zone"]

# Enable experimental features, like Stage 3 proposals.
experimental = ["temporal"]
Expand Down Expand Up @@ -130,6 +130,7 @@ tinystr = { workspace = true, optional = true }

# temporal deps
temporal_rs = { workspace = true, optional = true }
iana-time-zone = { version = "0.1.61", optional = true }

[target.'cfg(all(target_family = "wasm", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies]
web-time = { workspace = true, optional = true }
Expand Down
90 changes: 55 additions & 35 deletions core/engine/src/builtins/temporal/now.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use crate::{
property::Attribute,
realm::Realm,
string::StaticJsStrings,
Context, JsArgs, JsObject, JsResult, JsString, JsSymbol, JsValue,
Context, JsArgs, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_profiler::Profiler;
use temporal_rs::Now as NowInner;
use temporal_rs::{time::EpochNanoseconds, Instant, Now as NowInner, TimeZone};

use super::{
create_temporal_date, create_temporal_datetime, create_temporal_instant, create_temporal_time,
Expand Down Expand Up @@ -56,63 +56,83 @@ impl BuiltInObject for Now {
}

impl Now {
/// `Temporal.Now.timeZoneId ( )`
/// 2.2.1 `Temporal.Now.timeZoneId ( )`
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/proposal-temporal/#sec-temporal.now.timezone
#[allow(clippy::unnecessary_wraps)]
fn time_zone_id(_: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
// 1. Return ! SystemTimeZone().
Ok(JsString::from(NowInner::time_zone_id()?).into())
Ok(JsString::from(system_time_zone()?).into())
}

/// `Temporal.Now.instant()`
/// 2.2.2 `Temporal.Now.instant()`
fn instant(_: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
create_temporal_instant(NowInner::instant()?, None, context).map(Into::into)
let epoch_nanos = system_nanoseconds(context)?;
create_temporal_instant(Instant::from(epoch_nanos), None, context).map(Into::into)
}

/// `Temporal.Now.plainDateTime()`
/// 2.2.3 `Temporal.Now.plainDateTimeISO ( [ temporalTimeZoneLike ] )`
fn plain_datetime(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
let tz = args
.get_or_undefined(0)
.map(|v| to_temporal_timezone_identifier(v, context))
.transpose()?;
create_temporal_datetime(
NowInner::plain_datetime_iso_with_provider(tz, context.tz_provider())?,
None,
context,
)
.map(Into::into)
let (epoch_nanos, timezone) = resolve_system_values(args.get_or_undefined(0), context)?;
let datetime = NowInner::plain_datetime_iso_with_provider(
epoch_nanos,
timezone,
context.tz_provider(),
)?;
create_temporal_datetime(datetime, None, context).map(Into::into)
}

/// `Temporal.Now.zonedDateTime`
/// 2.2.4 `Temporal.Now.zonedDateTimeISO ( [ temporalTimeZoneLike ] )`
fn zoneddatetime(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
let timezone = args
.get_or_undefined(0)
.map(|v| to_temporal_timezone_identifier(v, context))
.transpose()?;
let zdt = NowInner::zoneddatetime_iso(timezone)?;
let (epoch_nanos, timezone) = resolve_system_values(args.get_or_undefined(0), context)?;
let zdt = NowInner::zoneddatetime_iso_with_system_values(epoch_nanos, timezone)?;
create_temporal_zoneddatetime(zdt, None, context).map(Into::into)
}

/// `Temporal.Now.plainDateISO`
/// 2.2.5 `Temporal.Now.plainDateISO ( [ temporalTimeZoneLike ] )`
fn plain_date(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
let tz = args
.get_or_undefined(0)
.map(|v| to_temporal_timezone_identifier(v, context))
.transpose()?;
let pd = NowInner::plain_date_iso_with_provider(tz, context.tz_provider())?;
let (epoch_nanos, timezone) = resolve_system_values(args.get_or_undefined(0), context)?;
let pd =
NowInner::plain_date_iso_with_provider(epoch_nanos, timezone, context.tz_provider())?;
create_temporal_date(pd, None, context).map(Into::into)
}

/// 2.2.6 `Temporal.Now.plainTimeISO ( [ temporalTimeZoneLike ] )`
fn plain_time(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
let tz = args
.get_or_undefined(0)
.map(|v| to_temporal_timezone_identifier(v, context))
.transpose()?;
let pt = NowInner::plain_time_iso_with_provider(tz, context.tz_provider())?;
let (epoch_nanos, timezone) = resolve_system_values(args.get_or_undefined(0), context)?;
let pt =
NowInner::plain_time_iso_with_provider(epoch_nanos, timezone, context.tz_provider())?;
create_temporal_time(pt, None, context).map(Into::into)
}
}

// `resolve_system_values` takes a `JsValue` representing a potential user provided time zone
// and returns the system time and time zone, resolving to the user time zone if provided
fn resolve_system_values(
timezone: &JsValue,
context: &mut Context,
) -> JsResult<(EpochNanoseconds, TimeZone)> {
let user_timezone = timezone
.map(|v| to_temporal_timezone_identifier(v, context))
.transpose()?;
let timezone = user_timezone.unwrap_or(TimeZone::try_from_str_with_provider(
&system_time_zone()?,
context.tz_provider(),
)?);
let epoch_nanos = EpochNanoseconds::try_from(context.clock().now().nanos_since_epoch())?;
Ok((epoch_nanos, timezone))
}

fn system_nanoseconds(context: &mut Context) -> JsResult<EpochNanoseconds> {
Ok(EpochNanoseconds::try_from(
context.clock().now().nanos_since_epoch(),
)?)
}

// TODO: Move system time zone fetching to context similiar to `Clock` and `TimeZoneProvider`
fn system_time_zone() -> JsResult<String> {
iana_time_zone::get_timezone()
.map_err(|e| JsNativeError::range().with_message(e.to_string()).into())
}

0 comments on commit a8aea9c

Please sign in to comment.