feat: implement precise Temporal Instant arithmetic
This commit is contained in:
@@ -86,7 +86,9 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
|
||||
instant_proto,
|
||||
core,
|
||||
&[
|
||||
("add", oxide_builtins::temporal::instant_add::<crate::vm::Vm> as *const (), 1),
|
||||
("equals", oxide_builtins::temporal::instant_equals::<crate::vm::Vm> as *const (), 1),
|
||||
("subtract", oxide_builtins::temporal::instant_subtract::<crate::vm::Vm> as *const (), 1),
|
||||
("toString", oxide_builtins::temporal::instant_to_string::<crate::vm::Vm> as *const (), 0),
|
||||
("valueOf", oxide_builtins::temporal::instant_value_of::<crate::vm::Vm> as *const (), 0),
|
||||
],
|
||||
|
||||
@@ -141,6 +141,45 @@ fn instant_compare_accepts_instances_strings_and_annotations() {
|
||||
assert!(r.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn instant_add_and_subtract_are_exact() {
|
||||
let mut vm = Vm::new();
|
||||
let r = eval(
|
||||
&mut vm,
|
||||
"let i = Temporal.Instant.fromEpochNanoseconds(1582966647747612578n);
|
||||
i.add({hours: 1, microseconds: 9007199254740991}).epochNanoseconds === 10590169502488603578n
|
||||
&& i.subtract('PT1.03125H').epochNanoseconds === 1582962935247612578n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(r.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn instant_add_ignores_receiver_subclass_for_result() {
|
||||
let mut vm = Vm::new();
|
||||
let r = eval(
|
||||
&mut vm,
|
||||
"class Sub extends Temporal.Instant { constructor(value) { super(value); } }
|
||||
let result = new Sub(10n).add({nanoseconds: 5});
|
||||
result instanceof Temporal.Instant && !(result instanceof Sub) && result.epochNanoseconds === 15n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(r.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn instant_arithmetic_rejects_date_units_and_out_of_range_results() {
|
||||
let mut vm = Vm::new();
|
||||
let r = eval(
|
||||
&mut vm,
|
||||
"let max = Temporal.Instant.fromEpochNanoseconds(8640000000000000000000n);
|
||||
(() => { try { max.add({nanoseconds: 1}); return false } catch (e) { return e instanceof RangeError } })()
|
||||
&& (() => { try { max.subtract({days: 1}); return false } catch (e) { return e instanceof RangeError } })()",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(r.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn instant_epoch_factories_validate_input_and_range() {
|
||||
let mut vm = Vm::new();
|
||||
|
||||
Reference in New Issue
Block a user