mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 10:41:11 +08:00
feat: 实现最小 BigInt 子集(字面量/算术/比较/构造器,Temporal 前置)
This commit is contained in:
@@ -13,8 +13,25 @@ impl Vm {
|
||||
self.regs[rd] = JsValue::float(lv.as_int() as f64 + rv.as_int() as f64);
|
||||
return Ok(());
|
||||
}
|
||||
if lv.is_bigint() && rv.is_bigint() {
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(lv) + self.bigint_value(rv));
|
||||
return Ok(());
|
||||
}
|
||||
// 注意:不能在此前置检查 BigInt 混合(`lv.is_bigint() || rv.is_bigint()`)——
|
||||
// 对象操作数(如 `{valueOf: () => 2n}`)需先 ToPrimitive 再判定,混合检查
|
||||
// 必须放在 coerce 之后。
|
||||
let lhs = self.coerce_primitive_bounded(lv, false)?;
|
||||
let rhs = self.coerce_primitive_bounded(rv, false)?;
|
||||
if lhs.is_bigint() && rhs.is_bigint() {
|
||||
// 包装对象 coerce 后暴露双 BigInt(如 Object(2n) + 2n)。
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(lhs) + self.bigint_value(rhs));
|
||||
return Ok(());
|
||||
}
|
||||
if lhs.is_bigint() != rhs.is_bigint() {
|
||||
// 包装对象 coerce 后暴露 BigInt:与另一非 BigInt 操作数混合加法必须抛
|
||||
// TypeError(规范不允许 BigInt 与 Number/String 相加)。
|
||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
||||
}
|
||||
if lhs.is_string() || rhs.is_string() {
|
||||
let lbytes = if lhs.is_string() { unsafe { (*lhs.as_string_ptr()).len() } } else { 0 };
|
||||
let rbytes = if rhs.is_string() { unsafe { (*rhs.as_string_ptr()).len() } } else { 0 };
|
||||
@@ -38,7 +55,12 @@ impl Vm {
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_neg(&mut self, rd: usize, a: usize) -> Result<(), String> {
|
||||
vm_trace!("NEG rd={} r{}={:?}", rd, a, self.regs[a]);
|
||||
let v = self.coerce_number_bounded(self.regs[a])?;
|
||||
let v = self.regs[a];
|
||||
if v.is_bigint() {
|
||||
self.regs[rd] = self.new_bigint(-self.bigint_value(v));
|
||||
return Ok(());
|
||||
}
|
||||
let v = self.coerce_number_bounded(v)?;
|
||||
self.regs[rd] = JsValue::float(-v);
|
||||
Ok(())
|
||||
}
|
||||
@@ -46,7 +68,12 @@ impl Vm {
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_unary_plus(&mut self, rd: usize, a: usize) -> Result<(), String> {
|
||||
vm_trace!("UNARY_PLUS rd={} r{}={:?}", rd, a, self.regs[a]);
|
||||
let v = self.coerce_number_bounded(self.regs[a])?;
|
||||
let v = self.regs[a];
|
||||
if v.is_bigint() {
|
||||
// 一元 + 对 BigInt 必须抛 TypeError(ToNumber(BigInt) 在隐式路径禁止)。
|
||||
return self.raise_type_error("Cannot convert a BigInt value to a number");
|
||||
}
|
||||
let v = self.coerce_number_bounded(v)?;
|
||||
self.regs[rd] = JsValue::float(v);
|
||||
Ok(())
|
||||
}
|
||||
@@ -59,8 +86,19 @@ impl Vm {
|
||||
self.regs[rd] = JsValue::float(lv.as_int() as f64 + rv.as_int() as f64);
|
||||
return Ok(());
|
||||
}
|
||||
if lv.is_bigint() && rv.is_bigint() {
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(lv) + self.bigint_value(rv));
|
||||
return Ok(());
|
||||
}
|
||||
let lhs = self.coerce_primitive_bounded(lv, false)?;
|
||||
let rhs = self.coerce_primitive_bounded(rv, false)?;
|
||||
if lhs.is_bigint() && rhs.is_bigint() {
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(lhs) + self.bigint_value(rhs));
|
||||
return Ok(());
|
||||
}
|
||||
if lhs.is_bigint() != rhs.is_bigint() {
|
||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
||||
}
|
||||
if lhs.is_string() || rhs.is_string() {
|
||||
let lbytes = if lhs.is_string() { unsafe { (*lhs.as_string_ptr()).len() } } else { 0 };
|
||||
let rbytes = if rhs.is_string() { unsafe { (*rhs.as_string_ptr()).len() } } else { 0 };
|
||||
@@ -90,9 +128,22 @@ impl Vm {
|
||||
self.regs[rd] = JsValue::float(lv.as_int() as f64 - rv.as_int() as f64);
|
||||
return Ok(());
|
||||
}
|
||||
let l = self.coerce_number_bounded(lv)?;
|
||||
let r = self.coerce_number_bounded(rv)?;
|
||||
self.regs[rd] = JsValue::float(l - r);
|
||||
if lv.is_bigint() && rv.is_bigint() {
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(lv) - self.bigint_value(rv));
|
||||
return Ok(());
|
||||
}
|
||||
let l = self.coerce_primitive_bounded(lv, false)?;
|
||||
let r = self.coerce_primitive_bounded(rv, false)?;
|
||||
if l.is_bigint() && r.is_bigint() {
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(l) - self.bigint_value(r));
|
||||
return Ok(());
|
||||
}
|
||||
if l.is_bigint() != r.is_bigint() {
|
||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
||||
}
|
||||
let ln = coercion::to_number(l);
|
||||
let rn = coercion::to_number(r);
|
||||
self.regs[rd] = JsValue::float(ln - rn);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -105,9 +156,22 @@ impl Vm {
|
||||
self.regs[rd] = JsValue::float(lv.as_int() as f64 * rv.as_int() as f64);
|
||||
return Ok(());
|
||||
}
|
||||
let l = self.coerce_number_bounded(lv)?;
|
||||
let r = self.coerce_number_bounded(rv)?;
|
||||
self.regs[rd] = JsValue::float(l * r);
|
||||
if lv.is_bigint() && rv.is_bigint() {
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(lv) * self.bigint_value(rv));
|
||||
return Ok(());
|
||||
}
|
||||
let l = self.coerce_primitive_bounded(lv, false)?;
|
||||
let r = self.coerce_primitive_bounded(rv, false)?;
|
||||
if l.is_bigint() && r.is_bigint() {
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(l) * self.bigint_value(r));
|
||||
return Ok(());
|
||||
}
|
||||
if l.is_bigint() != r.is_bigint() {
|
||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
||||
}
|
||||
let ln = coercion::to_number(l);
|
||||
let rn = coercion::to_number(r);
|
||||
self.regs[rd] = JsValue::float(ln * rn);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -120,9 +184,30 @@ impl Vm {
|
||||
self.regs[rd] = JsValue::float(lv.as_int() as f64 / rv.as_int() as f64);
|
||||
return Ok(());
|
||||
}
|
||||
let l = self.coerce_number_bounded(lv)?;
|
||||
let r = self.coerce_number_bounded(rv)?;
|
||||
self.regs[rd] = JsValue::float(l / r);
|
||||
if lv.is_bigint() && rv.is_bigint() {
|
||||
let r = self.bigint_value(rv);
|
||||
if r == 0 {
|
||||
return self.raise_error_kind("RangeError", "Division by zero");
|
||||
}
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(lv) / r);
|
||||
return Ok(());
|
||||
}
|
||||
let l = self.coerce_primitive_bounded(lv, false)?;
|
||||
let r = self.coerce_primitive_bounded(rv, false)?;
|
||||
if l.is_bigint() && r.is_bigint() {
|
||||
let rv = self.bigint_value(r);
|
||||
if rv == 0 {
|
||||
return self.raise_error_kind("RangeError", "Division by zero");
|
||||
}
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(l) / rv);
|
||||
return Ok(());
|
||||
}
|
||||
if l.is_bigint() != r.is_bigint() {
|
||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
||||
}
|
||||
let ln = coercion::to_number(l);
|
||||
let rn = coercion::to_number(r);
|
||||
self.regs[rd] = JsValue::float(ln / rn);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -135,9 +220,30 @@ impl Vm {
|
||||
self.regs[rd] = JsValue::float(lv.as_int() as f64 % rv.as_int() as f64);
|
||||
return Ok(());
|
||||
}
|
||||
let l = self.coerce_number_bounded(lv)?;
|
||||
let r = self.coerce_number_bounded(rv)?;
|
||||
self.regs[rd] = JsValue::float(l % r);
|
||||
if lv.is_bigint() && rv.is_bigint() {
|
||||
let r = self.bigint_value(rv);
|
||||
if r == 0 {
|
||||
return self.raise_error_kind("RangeError", "Division by zero");
|
||||
}
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(lv) % r);
|
||||
return Ok(());
|
||||
}
|
||||
let l = self.coerce_primitive_bounded(lv, false)?;
|
||||
let r = self.coerce_primitive_bounded(rv, false)?;
|
||||
if l.is_bigint() && r.is_bigint() {
|
||||
let rv = self.bigint_value(r);
|
||||
if rv == 0 {
|
||||
return self.raise_error_kind("RangeError", "Division by zero");
|
||||
}
|
||||
self.regs[rd] = self.new_bigint(self.bigint_value(l) % rv);
|
||||
return Ok(());
|
||||
}
|
||||
if l.is_bigint() != r.is_bigint() {
|
||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
||||
}
|
||||
let ln = coercion::to_number(l);
|
||||
let rn = coercion::to_number(r);
|
||||
self.regs[rd] = JsValue::float(ln % rn);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user