fix: Duration add/subtract 范围判据按存储分量加权和(对齐 IsValidDuration)

逐分量尾检误接受加权和落在 [2^53 s, 2^53 s + 86400 s) 的输入(各分量
均低于 2^53 秒上限而总和越界);按输入精确和校验又漏掉精确和低于上限、
而存储分量经 f64 舍入后达上限的情形。改按平衡后存储时间分量(含 days)
的纳秒加权和与 2^53 秒上限比较——校验对象与内部槽位的 float64 可表示
整数存储语义一致,判据与构造器/from 的 validate_duration_values 同式。
补加权和边界钉(恰 = 2^53 s 抛 RangeError、2^53 s − 1 s 通过并平衡到
day 级)。
This commit is contained in:
2026-09-12 08:27:40 +00:00
parent c589336393
commit 4538dcd9a8
2 changed files with 35 additions and 16 deletions
@@ -2521,6 +2521,30 @@ fn duration_subtract_equals_add_negated() {
assert_eq!(str_val(&vm, r), "RangeError");
}
#[test]
fn duration_add_weighted_sum_range_boundary() {
let mut vm = Vm::new();
// 范围判据按平衡后时间分量加权和(spec IsValidDuration),非逐分量:
// days 和 104249991374 + 时间 27392 s 恰 = 2^53 s → RangeError(逐分量均低于上限);
// 同输入减 1 s(总和 2^53 s − 1 s)→ 通过并平衡到 day/hour/minute/second。
let r = eval(
&mut vm,
"(() => {
const a = new Temporal.Duration(0, 0, 0, 52083464098, 3, 53, 20);
const b = {days: 52166527276, hours: 3, minutes: 43, seconds: 12};
const kind = (fn) => { try { fn(); return 'no'; } catch (e) { return e.constructor.name; } };
return [
kind(() => a.add(b)),
kind(() => new Temporal.Duration(0, 0, 0, -52083464098, -3, -53, -20).subtract(b)),
kind(() => new Temporal.Duration(0, 0, 0, 52083464098, 3, 53, 19).add(b)),
new Temporal.Duration(0, 0, 0, 52083464098, 3, 53, 19).add(b).toString(),
].join('|');
})()",
)
.unwrap();
assert_eq!(str_val(&vm, r), "RangeError|RangeError|no|P104249991374DT7H36M31S");
}
#[test]
fn duration_equals_compares_all_components() {
let mut vm = Vm::new();