-
Notifications
You must be signed in to change notification settings - Fork 19
Add with to PlainYearMonth #231
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fantastic!
I have one issue, but it doesn't really have anything to do with the code, so much as it does some weird oddities with PlainYearMonth
. I tried to give as detailed of an explanation as I could. Let me know what you'd prefer.
use super::*; | ||
|
||
#[test] | ||
fn test_plain_year_month_with() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
praise: great tests!
src/builtins/core/year_month.rs
Outdated
let with_day = base.with(partial, None).unwrap(); | ||
assert_eq!(with_day.iso_year(), 2025); // year is not changed | ||
assert_eq!(with_day.iso_month(), 3); // month is not changed | ||
assert_eq!(with_day.iso.day, 15); // day is changed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: so this one is a little tricky, but the ISO day property shouldn't be touched.
For reference, see the basic PlainYearMonth.prototype.with test
src/builtins/core/date.rs
Outdated
@@ -78,6 +78,7 @@ impl PartialDate { | |||
}) | |||
} | |||
|
|||
crate::impl_with_fallback_method!(with_fallback_year_month, PlainYearMonth); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (part 2 on test review comment): so this macro impl specifically on PartialDate
is a bit problematic for specifically PlainYearMonth
.
The method steps at play here are 6-7:
6. Let partialYearMonth be ? [PrepareCalendarFields](https://tc39.es/proposal-temporal/#sec-temporal-preparecalendarfields)(calendar, temporalYearMonthLike, « year, month, month-code », « », partial).
7. Set fields to [CalendarMergeFields](https://tc39.es/proposal-temporal/#sec-temporal-calendarmergefields)(calendar, fields, partialYearMonth).
PrepareCalendarFields
is a bit of a complex abstract operations that's main purpose is to pull fields from a JavaScript object. In order to handle this, the partial objects were created.
You correctly noted that the partial cannot be empty when submit into with
, but the actual assertion technically occurs here in step 6, not 3 (that abstract operation does ALOT).
This method implemented by this macro is temporal_rs
's answer for step 7. The only issue is that day should never be set downstream by the caller due to step 6.
The simple solution would be to manually implement a with_fallback_year_month
that does not touch the partial.day
(like the other year_month method above this).
The other solution (that after typing this all out I'm more convinced is the correct approach) is to move that invariant of not touching the day field into the type system and create a PartialYearMonth
struct that can then be used on all PlainYearMonth
paths that are using PartialDate
.
The second solution is probably a bit of scope creep, so if you'd like to go with the first solution, that's fine by me. We can review and merge this, and I'll open up another issue for implementing PartialYearMonth
.
If you want to do the second solution, I think PartialYearMonth
should look something like:
struct PartialYearMonth {
pub year: Option<i32>,
pub month: Option<u8>,
pub month_code: Option<MonthCode>,
pub era: Option<TinyAsciiStr<19>>,
pub era_year: Option<i32>,
pub calendar: Calendar,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another solution could be to make the function return an Err
if the PartialDate day
field is populated, and then just use the regular macro?
But I like the type system approach of PartialYearMonth
. (If you do, it looks like it should go in year_month.rs
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another solution could be to make the function return an
Err
if the PartialDateday
field is populated, and then just use the regular macro?
Yeah, the incoming partial would still have to throw on partail.day.is_some()
, but the regular macro still sets the day according to the fallback, which would still be invalid as well I believe. The day field is "resolved" by the calendar, at least according to the specification, in step 2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ve implemented a solution that avoids modifying the day
field while still using the macro. Instead of implementing a separate with_fallback_year_month
or type system, I’ve tweaked the macro to require explicit day specification, so PlainYearMonth can use it without setting day.
It’s set to None via ..Default::default(), but I’m concerned this doesn’t strictly align with spec step 6 of 9.3.13. Is this okay, or should I continue with the type system instead?
Check out the latest commit. I’ve also changed the test cases which now ignores any attempt to change the day
of a PlainYearMonth
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw the change you had made to the macro 😃 It's a pretty creative one!
Strictly aligning to the spec on step 6 is incredibly hard due to its reliance on JavaScript objects, and essentially requires more of an interpretation rather than step by step adherence, which is how the partial objects came to be.
The best way to test is to see if it passes the test262 test suite. Have you run the test262 test suite with Boa by chance to test conformance?
I still have to do a more proper review, but I think I'm fine with merging this current approach for now. But as mentioned above, I think long term moving to a PartialYearMonth
struct is the best option overall. So a follow up PR to complete that is definitely best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The macro trick was all @sffc—credit goes to him😅. Right now, testing Temporal with Boa doesn’t seem to work for me🤔. I suspect it may relate to the MonthCode change in temporal, I’m not entirely sure. If the fix is trivial, I’ll try and run Test262.
Here are some of the errors i am experiencing
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a method that returns `Result`
--> core/engine/src/builtins/temporal/plain_date/mod.rs:334:19
|
321 | fn get_era(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
| ------------------------------------------------------------------------------- this function returns a `Result`
...
334 | .era()?
| ^ use `.ok_or(...)?` to provide an error compatible with `Result<value::JsValue, error::JsError>`
|
= help: the trait `FromResidual<std::option::Option<Infallible>>` is not implemented for `Result<value::JsValue, error::JsError>`
= help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
error[E0599]: `TinyAsciiStr<16>` is not an iterator
--> core/engine/src/builtins/temporal/plain_date/mod.rs:335:14
|
332 | Ok(date
| ____________-
333 | | .inner
334 | | .era()?
335 | | .map(|s| JsString::from(s.as_str()))
| | -^^^ `TinyAsciiStr<16>` is not an iterator
| |_____________|
|
|
::: /Users/sebastianmatthews/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinystr-0.8.1/src/ascii.rs:15:1
|
15 | pub struct TinyAsciiStr<const N: usize> {
| --------------------------------------- doesn't satisfy `TinyAsciiStr<16>: std::iter::Iterator`
|
= note: the following trait bounds were not satisfied:
`TinyAsciiStr<16>: std::iter::Iterator`
which is required by `&mut TinyAsciiStr<16>: std::iter::Iterator`
`str: std::iter::Iterator`
which is required by `&mut str: std::iter::Iterator`
There is a total of 34 errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has this been rebased or merged with main recently? I thought more or less Boa was up to date ... but maybe its a bit more out of sync then I had thought. I can have an update complete by tonight.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've rebased onto the main branch and successfully tested with the test262 suite.
Note: I modified the get_option
call in boa, removing the .unwrap_or_default();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following up on this PR for the CI failure.
We've started checking in the cpp bindings for temporal_capi
. Since this PR makes a change to temporal_capi
. You'll need to update the bindings. To do so, simply run cargo run -p diplomat-gen
. This will update the bindings and then you just add them to history. Let me know if you have any issues.
src/builtins/core/year_month.rs
Outdated
@@ -182,13 +182,35 @@ impl PlainYearMonth { | |||
self.calendar.identifier() | |||
} | |||
|
|||
/// Returns the calendar day value. | |||
pub fn day(&self) -> TemporalResult<u8> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was double checking the PR and noticed this method. This should be removed as PlainYearMonth
has no day accessor on the builtin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm having an issue with the FFI bindings from boa-dev/temporal to boa. When I run cargo test
in boa I get the error:
core/engine/src/builtins/temporal/plain_year_month/mod.rs:372:53
let result = year_month.inner.with(partial, overflow)?;
expected `Option<ArithmeticOverflow>`, found `ArithmeticOverflow`
I ran cargo run -p diplomat-gen
. PlainYearMonth.hpp shows a change from ArithmeticOverflow to ArithmeticOverflow_option, so it appears the bindings were updated, yet the error persists🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that looks like it's the call from boa_engine
that is causing the compilation error.
You'd need to update the code in Boa. The get_option
call will need it's unwrap_or_default
removed
EDIT: just to note, that failure shouldn't affect this PR. Currently, it looks like you only need to run Rustfmt 😄
…endencies group (boa-dev#242) Bumps the rust-dependencies group with 1 update: [jiff-tzdb](https://github.com/BurntSushi/jiff). Updates `jiff-tzdb` from 0.1.2 to 0.1.3 <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md">jiff-tzdb's changelog</a>.</em></p> <blockquote> <h1>0.1.29 (2025-02-02)</h1> <p>This release includes a few small enhancements and a bug fix. In particular, there is now Serde support for <code>TimeZone</code> and the <code>ISOWeekDate</code> API has been filled out a bit more.</p> <p>Unless a serious issue is uncovered, my plan is that this will be the last release before <code>jiff 0.2</code>.</p> <p>Enhancements:</p> <ul> <li><a href="https://redirect.github.com/BurntSushi/jiff/issues/89">#89</a>: Opt-in support for using Serde with <code>jiff::tz::TimeZone</code> has been added.</li> <li><a href="https://redirect.github.com/BurntSushi/jiff/issues/227">#227</a>: The <code>civil::ISOWeekDate</code> API has been beefed up with a few convenience methods.</li> <li><a href="https://redirect.github.com/BurntSushi/jiff/issues/233">#233</a>: Add <code>tz::Offset::round</code> for rounding time zone offsets.</li> </ul> <p>Bug fixes:</p> <ul> <li><a href="https://redirect.github.com/BurntSushi/jiff/issues/231">#231</a>: Use more flexible offset equality when parsing offsets with fractional minutes.</li> </ul> <h1>0.1.28 (2025-01-27)</h1> <p>This is a small release that just removes the dev-dependency on <code>serde_yml</code>. It has been replaced with the deprecated <code>serde_yaml</code>. See <a href="https://x.com/davidtolnay/status/1883906113428676938">this post about <code>serde_yml</code> shenanigans</a> for why this was done. Note that this was only a dev-dependency and thus doesn't impact folks using Jiff.</p> <p>Bug fixes:</p> <ul> <li><a href="https://redirect.github.com/BurntSushi/jiff/pull/225">#225</a>: Remove dependency on <code>serde_yml</code> in favor of <code>serde_yaml</code>.</li> </ul> <h1>0.1.27 (2025-01-25)</h1> <p>This is a small release with a bug fix for precision loss in some cases when doing arithmetic on <code>Timestamp</code> or <code>Zoned</code>.</p> <p>Bug fixes:</p> <ul> <li><a href="https://redirect.github.com/BurntSushi/jiff/issues/223">#223</a>: Fix the check for fractional seconds before taking the fast path.</li> </ul> <p>0.1.26 (2025-01-23)</p> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/BurntSushi/jiff/commit/08571714a9ecaa37bff86b480433fae2760756a2"><code>0857171</code></a> jiff-tzdb-0.1.3</li> <li><a href="https://github.com/BurntSushi/jiff/commit/300886fef3d1d14511c62111feed3340f96a6ce2"><code>300886f</code></a> jiff-diesel-0.1.3</li> <li><a href="https://github.com/BurntSushi/jiff/commit/252a0806dc3c6bd4f6217f7029709a9e24994998"><code>252a080</code></a> jiff-sqlx-0.1.1</li> <li><a href="https://github.com/BurntSushi/jiff/commit/fdd352efe195583076c032ebcc4b31defb6a819c"><code>fdd352e</code></a> changelog: 0.2.2</li> <li><a href="https://github.com/BurntSushi/jiff/commit/5faa976b9c4fd487a708b8aaf6273840d91f0794"><code>5faa976</code></a> ci: try the Rust 2024 doc test perf improvement for Windows</li> <li><a href="https://github.com/BurntSushi/jiff/commit/c789dd50b9ea376d275b17ed1ed5235b53bb5214"><code>c789dd5</code></a> fmt: disable snapshot tests on core-only</li> <li><a href="https://github.com/BurntSushi/jiff/commit/35b0c4d422ffce699cf076a65714cab5f55fd85a"><code>35b0c4d</code></a> ci: break <code>./scripts/test</code> into pieces...</li> <li><a href="https://github.com/BurntSushi/jiff/commit/9dd4b9337d3a6967afed639c4e826cfeb2eb08b7"><code>9dd4b93</code></a> ci: bump to wasmtime 30.0.1</li> <li><a href="https://github.com/BurntSushi/jiff/commit/fa62c4fbd77195b540a90a7d979cee2ae17351ff"><code>fa62c4f</code></a> scripts: fix <code>test-wasm</code></li> <li><a href="https://github.com/BurntSushi/jiff/commit/1471f752e5850692d6e19bbb64fe8cd2d3556d26"><code>1471f75</code></a> test: move <code>test</code> and <code>test-wasm</code> into <code>scripts</code></li> <li>Additional commits viewable in <a href="https://github.com/BurntSushi/jiff/compare/jiff-tzdb-0.1.2...jiff-tzdb-0.1.3">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Fixes boa-dev#139 Tests adapted from sample code in https://tc39.es/proposal-temporal/docs/duration.html under total now pass :) I have a question in duration.rs about return types! There's also another question in normalized.rs regarding some code i'd like to refactor that makes this PR quite a bit larger than it needs to be
if you want to fix the lint errors you should run:
and fix the errors in the code til there are none left:) |
Yeah, I'm not actually sure of a good way to fix this. Although, I am curious if there is a way. In the meantime, just annotate the macro with the recommend allow clippy lint: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks for working on this!
Restructured pull request of #216
Worked with @HenrikTennebekk on #143
Had to change temporal_capi/plain_year_month.rs hope this is fine?