mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: 关系比较处理器补 Symbol 守卫,替换 BigInt 混合检查
This commit is contained in:
@@ -29,8 +29,8 @@ impl Vm {
|
|||||||
vm_trace!("LT rd={} r{}={:?} r{}={:?}", rd, a, self.regs[a], b, self.regs[b]);
|
vm_trace!("LT rd={} r{}={:?} r{}={:?}", rd, a, self.regs[a], b, self.regs[b]);
|
||||||
let va = self.coerce_primitive_bounded(self.regs[a], false)?;
|
let va = self.coerce_primitive_bounded(self.regs[a], false)?;
|
||||||
let vb = self.coerce_primitive_bounded(self.regs[b], false)?;
|
let vb = self.coerce_primitive_bounded(self.regs[b], false)?;
|
||||||
if (va.is_bigint() || vb.is_bigint()) && (va.is_symbol() || vb.is_symbol()) {
|
if va.is_symbol() || vb.is_symbol() {
|
||||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
return self.raise_type_error("Cannot convert a Symbol value to a number");
|
||||||
}
|
}
|
||||||
match coercion::relational_compare(va, vb) {
|
match coercion::relational_compare(va, vb) {
|
||||||
Some(r) => self.regs[rd] = JsValue::bool(r),
|
Some(r) => self.regs[rd] = JsValue::bool(r),
|
||||||
@@ -47,8 +47,8 @@ impl Vm {
|
|||||||
vm_trace!("GT rd={} r{}={:?} r{}={:?}", rd, a, self.regs[a], b, self.regs[b]);
|
vm_trace!("GT rd={} r{}={:?} r{}={:?}", rd, a, self.regs[a], b, self.regs[b]);
|
||||||
let va = self.coerce_primitive_bounded(self.regs[a], false)?;
|
let va = self.coerce_primitive_bounded(self.regs[a], false)?;
|
||||||
let vb = self.coerce_primitive_bounded(self.regs[b], false)?;
|
let vb = self.coerce_primitive_bounded(self.regs[b], false)?;
|
||||||
if (va.is_bigint() || vb.is_bigint()) && (va.is_symbol() || vb.is_symbol()) {
|
if va.is_symbol() || vb.is_symbol() {
|
||||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
return self.raise_type_error("Cannot convert a Symbol value to a number");
|
||||||
}
|
}
|
||||||
match coercion::relational_compare(vb, va) {
|
match coercion::relational_compare(vb, va) {
|
||||||
Some(r) => self.regs[rd] = JsValue::bool(r),
|
Some(r) => self.regs[rd] = JsValue::bool(r),
|
||||||
@@ -65,8 +65,8 @@ impl Vm {
|
|||||||
vm_trace!("LTE rd={} r{}={:?} r{}={:?}", rd, a, self.regs[a], b, self.regs[b]);
|
vm_trace!("LTE rd={} r{}={:?} r{}={:?}", rd, a, self.regs[a], b, self.regs[b]);
|
||||||
let va = self.coerce_primitive_bounded(self.regs[a], false)?;
|
let va = self.coerce_primitive_bounded(self.regs[a], false)?;
|
||||||
let vb = self.coerce_primitive_bounded(self.regs[b], false)?;
|
let vb = self.coerce_primitive_bounded(self.regs[b], false)?;
|
||||||
if (va.is_bigint() || vb.is_bigint()) && (va.is_symbol() || vb.is_symbol()) {
|
if va.is_symbol() || vb.is_symbol() {
|
||||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
return self.raise_type_error("Cannot convert a Symbol value to a number");
|
||||||
}
|
}
|
||||||
match coercion::relational_compare(vb, va) {
|
match coercion::relational_compare(vb, va) {
|
||||||
Some(r) => self.regs[rd] = JsValue::bool(!r),
|
Some(r) => self.regs[rd] = JsValue::bool(!r),
|
||||||
@@ -83,8 +83,8 @@ impl Vm {
|
|||||||
vm_trace!("GTE rd={} r{}={:?} r{}={:?}", rd, a, self.regs[a], b, self.regs[b]);
|
vm_trace!("GTE rd={} r{}={:?} r{}={:?}", rd, a, self.regs[a], b, self.regs[b]);
|
||||||
let va = self.coerce_primitive_bounded(self.regs[a], false)?;
|
let va = self.coerce_primitive_bounded(self.regs[a], false)?;
|
||||||
let vb = self.coerce_primitive_bounded(self.regs[b], false)?;
|
let vb = self.coerce_primitive_bounded(self.regs[b], false)?;
|
||||||
if (va.is_bigint() || vb.is_bigint()) && (va.is_symbol() || vb.is_symbol()) {
|
if va.is_symbol() || vb.is_symbol() {
|
||||||
return self.raise_type_error("Cannot mix BigInt and other types, use explicit conversions");
|
return self.raise_type_error("Cannot convert a Symbol value to a number");
|
||||||
}
|
}
|
||||||
match coercion::relational_compare(va, vb) {
|
match coercion::relational_compare(va, vb) {
|
||||||
Some(r) => self.regs[rd] = JsValue::bool(!r),
|
Some(r) => self.regs[rd] = JsValue::bool(!r),
|
||||||
|
|||||||
@@ -157,3 +157,27 @@ fn eval_string_relational_utf16_code_unit_order() {
|
|||||||
assert_eq!(eval(source), expected, "source: {source}");
|
assert_eq!(eval(source), expected, "source: {source}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_relational_symbol_throws() {
|
||||||
|
// 关系比较任一侧为 Symbol 时按 ToNumber 抛 TypeError(规范 13.7.5 步骤 4/5)。
|
||||||
|
assert_eq!(
|
||||||
|
eval("Object(Symbol()) <= ''"),
|
||||||
|
"vm error: uncaught TypeError: Cannot convert a Symbol value to a number"
|
||||||
|
);
|
||||||
|
// symbol 与 bigint 混合时 symbol 消息优先(ToNumber 先于混合判定)。
|
||||||
|
assert_eq!(
|
||||||
|
eval("Object(Symbol()) < 1n"),
|
||||||
|
"vm error: uncaught TypeError: Cannot convert a Symbol value to a number"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
eval("Object(Symbol()) > 1n"),
|
||||||
|
"vm error: uncaught TypeError: Cannot convert a Symbol value to a number"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
eval("1n >= Object(Symbol())"),
|
||||||
|
"vm error: uncaught TypeError: Cannot convert a Symbol value to a number"
|
||||||
|
);
|
||||||
|
// 松散等值对 symbol 不抛,返回 false(回归钉)。
|
||||||
|
assert_eq!(eval("Object(Symbol()) == 'Symbol()'"), "false");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user