feat(napi): support std::time::SystemTime - #3347
#3347feat(napi): support std::time::SystemTime#3347bg-softcom wants to merge 1 commit into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds ChangesSystemTime N-API Binding and Date Module Refactor
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant JSCaller
participant NAPIExample
participant SystemTimeBinding
participant DateHelpers
participant JavaScriptDate
JSCaller->>NAPIExample: systemTimeToMillis(Date)
NAPIExample->>SystemTimeBinding: FromNapiValue
SystemTimeBinding->>DateHelpers: get_date_millis
DateHelpers->>JavaScriptDate: napi_get_date_value
JavaScriptDate-->>DateHelpers: epoch milliseconds
DateHelpers-->>SystemTimeBinding: milliseconds
SystemTimeBinding-->>NAPIExample: SystemTime
NAPIExample-->>JSCaller: number
JSCaller->>NAPIExample: systemTimeReturn()
NAPIExample->>SystemTimeBinding: ToNapiValue
SystemTimeBinding->>DateHelpers: date_from_millis
DateHelpers->>JavaScriptDate: napi_create_date
JavaScriptDate-->>JSCaller: Date
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
examples/napi/__tests__/values.spec.ts (1)
2069-2086: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd a pre-epoch Date round-trip test to lock regression coverage.
Please add a case like
new Date(-1)forsystemTimeToMillisso Line 36 inexamples/napi/src/date.rscan’t regress back to a panic path unnoticed.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/napi/__tests__/values.spec.ts` around lines 2069 - 2086, Add a new test case using Napi5Test to verify that systemTimeToMillis correctly handles pre-epoch dates (negative timestamps). Create a test that instantiates a Date with a negative value such as new Date(-1) and verifies that systemTimeToMillis returns the expected result, ensuring that the implementation at Line 36 in examples/napi/src/date.rs does not regress into a panic path. This test should be placed alongside the existing Date to SystemTime tests to provide comprehensive coverage for edge cases.crates/napi/src/bindgen_runtime/js_values/date/chrono.rs (1)
107-119: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse
date_from_millishere for consistency and bounds checking.
NaiveDateTime::to_napi_value(line 29) goes through the shareddate_from_millishelper, but thisDateTime<Tz>impl callssys::napi_create_datedirectly. This bypasses the timeClip range validation (abs() > 8.64e15) that the helper provides, so an out-of-rangetimestamp_millis()can silently produce an invalid JSDateinstead of surfacing an error. Aligning it with the helper also matches the PR's de-duplication goal.♻️ Proposed change
impl<Tz: TimeZone> ToNapiValue for DateTime<Tz> { unsafe fn to_napi_value(env: sys::napi_env, val: DateTime<Tz>) -> Result<sys::napi_value> { - let mut ptr = std::ptr::null_mut(); - let millis_since_epoch_utc = val.timestamp_millis() as f64; - - check_status!( - unsafe { sys::napi_create_date(env, millis_since_epoch_utc, &mut ptr) }, - "Failed to convert rust type `DateTime` into napi value", - )?; - - Ok(ptr) + let millis_since_epoch_utc = val.timestamp_millis() as f64; + unsafe { date_from_millis(env, millis_since_epoch_utc) } } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/napi/src/bindgen_runtime/js_values/date/chrono.rs` around lines 107 - 119, The `DateTime<Tz>` implementation of `to_napi_value` is calling `sys::napi_create_date` directly instead of reusing the shared `date_from_millis` helper that is already used in the `NaiveDateTime::to_napi_value` implementation. Replace the direct call to `sys::napi_create_date` with a call to the `date_from_millis` helper function, passing the result of `val.timestamp_millis()` as the argument. This ensures the helper's timeClip range validation is applied to catch out-of-range timestamps and maintains consistency across implementations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/napi/src/bindgen_runtime/js_values/date.rs`:
- Around line 1-2: Change the feature gate on the chrono module declaration from
`#[cfg(feature = "chrono")]` to `#[cfg(feature = "chrono_date")]` to match the
actual feature name defined in Cargo.toml. The `chrono_date` feature is the one
declared in the manifest as a composite feature that includes chrono and napi5,
so the mod chrono statement needs to reference this correct feature name for the
module to compile when the feature is enabled.
In `@crates/napi/src/bindgen_runtime/js_values/date/common.rs`:
- Around line 59-64: The validation guard checking whether
millis_since_epoch.abs() exceeds 8.64e15 does not catch NaN values, since NaN
comparisons always return false, allowing NaN to bypass the check and silently
create an Invalid Date object. Add a finiteness check using is_finite() on
millis_since_epoch before or alongside the existing magnitude check to ensure
NaN values are rejected and return an appropriate error, preventing invalid
dates from being silently created when NaN is passed as input.
In `@examples/napi/src/date.rs`:
- Around line 34-37: The system_time_to_millis function calls unwrap() on the
result of input.duration_since(UNIX_EPOCH), which will panic if the input is a
pre-epoch timestamp. Remove the unwrap() call and instead handle the error case
gracefully. Either check if the result is an error and handle pre-epoch
timestamps appropriately (such as returning 0, a negative value, or calculating
the duration differently), or use a method like unwrap_or() to provide a safe
default behavior that prevents panicking on valid pre-epoch SystemTime values.
---
Nitpick comments:
In `@crates/napi/src/bindgen_runtime/js_values/date/chrono.rs`:
- Around line 107-119: The `DateTime<Tz>` implementation of `to_napi_value` is
calling `sys::napi_create_date` directly instead of reusing the shared
`date_from_millis` helper that is already used in the
`NaiveDateTime::to_napi_value` implementation. Replace the direct call to
`sys::napi_create_date` with a call to the `date_from_millis` helper function,
passing the result of `val.timestamp_millis()` as the argument. This ensures the
helper's timeClip range validation is applied to catch out-of-range timestamps
and maintains consistency across implementations.
In `@examples/napi/__tests__/values.spec.ts`:
- Around line 2069-2086: Add a new test case using Napi5Test to verify that
systemTimeToMillis correctly handles pre-epoch dates (negative timestamps).
Create a test that instantiates a Date with a negative value such as new
Date(-1) and verifies that systemTimeToMillis returns the expected result,
ensuring that the implementation at Line 36 in examples/napi/src/date.rs does
not regress into a panic path. This test should be placed alongside the existing
Date to SystemTime tests to provide comprehensive coverage for edge cases.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 01336344-f8d2-40e0-97a5-d7b39bc45b7c
⛔ Files ignored due to path filters (1)
examples/napi/__tests__/__snapshots__/values.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (13)
crates/backend/src/typegen.rscrates/napi/src/bindgen_runtime/js_values.rscrates/napi/src/bindgen_runtime/js_values/date.rscrates/napi/src/bindgen_runtime/js_values/date/chrono.rscrates/napi/src/bindgen_runtime/js_values/date/common.rscrates/napi/src/bindgen_runtime/js_values/date/time.rsexamples/napi/__tests__/__snapshots__/values.spec.ts.mdexamples/napi/__tests__/values.spec.tsexamples/napi/example.wasi-browser.jsexamples/napi/example.wasi.cjsexamples/napi/index.cjsexamples/napi/index.d.ctsexamples/napi/src/date.rs
|
@codex review |
|
Codex Review: Didn't find any major issues. Already looking forward to the next diff. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Reviewed this against latest Merge conflictMerging yarn workspace @examples/napi build
yarn workspace @examples/napi test __tests__/values.spec.ts -uThe re-gate of Review — verdict: Approve with nitsDid a multi-lens adversarial review (conversion correctness, refactor fidelity, feature gating, codegen/tests, API consistency). The
Fixes ready to landI've resolved the merge + addressed A/B/C on a local branch (D kept as-is — reverting it would re-duplicate what the refactor de-duplicated). The changes: A — cover pre-epoch conversion in both directionsNapi5Test('Pre-epoch Date to SystemTime test', (t) => {
const fixture = new Date(-1000)
t.is(systemTimeToMillis(fixture), -1000)
})
Napi5Test('Pre-epoch Date from SystemTime test', (t) => {
const fixture = systemTimeReturnNegative()
t.true(fixture instanceof Date)
t.is(fixture?.toISOString(), '1969-12-31T23:59:59.000Z')
})// examples/napi/src/date.rs
#[napi]
pub fn system_time_return_negative() -> SystemTime {
// 1969-12-31T23:59:59.000, i.e. one second before the UNIX epoch
UNIX_EPOCH - std::time::Duration::from_secs(1)
}B — actually assert the error messageNapi5Test('NaN Date to SystemTime test', (t) => {
const fixture = new Date(NaN)
t.throws(() => systemTimeToMillis(fixture), {
code: 'DateExpected',
message: 'Date cannot be represented as rust type `SystemTime`',
})
})C — make all three Date conversions consistentimpl<Tz: TimeZone> ToNapiValue for DateTime<Tz> {
unsafe fn to_napi_value(env: sys::napi_env, val: DateTime<Tz>) -> Result<sys::napi_value> {
let millis_since_epoch_utc = val.timestamp_millis() as f64;
unsafe { date_from_millis(env, millis_since_epoch_utc) }
}
}With these applied: 169 tests pass (was 167), I couldn't push these directly since "Allow edits by maintainers" is off on this PR. If you enable it I'll push the resolved branch; otherwise the diffs above apply cleanly on top of a |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/napi/CHANGELOG.md`:
- Line 191: The changelog entry in CHANGELOG.md uses awkward subsystem wording,
so update the text in the release note entry for the non-dyn-symbols change to
use the hyphenated form consistently. Locate the existing “add back non
dyn-symbols behavior” entry and revise only the wording so it reads as a proper
hyphenated subsystem name.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 5edd666a-0601-41ee-a029-feb77aad20ad
⛔ Files ignored due to path filters (1)
examples/napi/__tests__/__snapshots__/values.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (7)
crates/napi/CHANGELOG.mdexamples/napi/__tests__/__snapshots__/values.spec.ts.mdexamples/napi/__tests__/values.spec.tsexamples/napi/example.wasi-browser.jsexamples/napi/example.wasi.cjsexamples/napi/index.cjsexamples/napi/index.d.cts
✅ Files skipped from review due to trivial changes (1)
- examples/napi/tests/snapshots/values.spec.ts.md
🚧 Files skipped from review as they are similar to previous changes (5)
- examples/napi/example.wasi-browser.js
- examples/napi/index.d.cts
- examples/napi/example.wasi.cjs
- examples/napi/index.cjs
- examples/napi/tests/values.spec.ts
|
@Brooooooklyn, Could you look at this again, please? My colleague had applied the patches while I was on vacation, and I have rebased the changes on top of |
Added support for
std::time::SystemTimebased on existing support forchrono::DateTime.For that, I've split
date.rsinto 4 files:date.rscontaining module declarations for other fileschrono.rscontaining previousdate.rscontent with minor changes (more below)time.rscontaining new code forstd::time::SystemTimesupportcommon.rscontaining common logic used bychrono.rsandtime.rs.I've extracted validation and conversion between
f64and JSDateinto thin helper functions which are reused by existing and new code. This changes the error messages in some cases to avoid referencing the specific type for which the conversion is performed.Summary by CodeRabbit
New Features
SystemTimevalues to and from JavaScriptDateobjects.Tests