feat: 支持可选链空值合并与逻辑赋值

This commit is contained in:
2026-06-18 15:26:16 +08:00
parent 3784db7b17
commit 32af37963e
14 changed files with 869 additions and 87 deletions
@@ -23,6 +23,12 @@ impl Vm {
}
}
#[inline(always)]
pub(crate) fn dispatch_nullish(&mut self, rd: usize, a: usize, b: usize) {
let val = self.regs[a];
self.regs[rd] = if val.is_nullish() { self.regs[b] } else { val };
}
#[inline(always)]
pub(crate) fn dispatch_not(&mut self, rd: usize, a: usize) {
let b = !coercion::to_boolean(self.regs[a], self.kernel_core.string_forge().as_ref());
+31 -5
View File
@@ -687,6 +687,13 @@ impl Vm {
}
}
OpCode::JMP_IF_NULLISH => {
if self.regs[rd].is_nullish() {
let offset = opcode::offset16(instr) as isize;
self.pc = ((self.pc as isize) + offset - 1) as usize;
}
}
OpCode::LOAD_VAR => {
if a == 254
&& self.frames.last().map(|frame| frame.is_derived_constructor).unwrap_or(false)
@@ -1016,15 +1023,30 @@ impl Vm {
}
OpCode::DELETE_PROP_STATIC => {
let _ = self.bytecode[self.pc];
let prop_idx = self.bytecode[self.pc] as usize;
self.pc += 1;
throw_err!(self, TypeError, "property deletion not supported");
let key_val = self.constants.get(prop_idx).copied().unwrap_or_else(JsValue::undefined);
let prop_name_si = self.property_key_si(key_val);
let Some(obj_ptr) = self.checked_object_ptr(self.regs[rd], "delete on non-object")? else {
continue;
};
let obj = unsafe { &mut *obj_ptr };
if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) {
obj.set_prop_at(pos, JsValue::undefined());
}
self.regs[rd] = JsValue::bool(true);
}
OpCode::DELETE_PROP_DYNAMIC => {
let _ = self.regs[a];
let _ = self.regs[b];
throw_err!(self, TypeError, "property deletion not supported");
let prop_name_si = self.property_key_si(self.regs[b]);
let Some(obj_ptr) = self.checked_object_ptr(self.regs[rd], "delete on non-object")? else {
continue;
};
let obj = unsafe { &mut *obj_ptr };
if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) {
obj.set_prop_at(pos, JsValue::undefined());
}
self.regs[rd] = JsValue::bool(true);
}
OpCode::INSTANCEOF => {
@@ -1047,6 +1069,10 @@ impl Vm {
self.dispatch_or(rd, a, b);
}
OpCode::NULLISH => {
self.dispatch_nullish(rd, a, b);
}
OpCode::INC_PRE => {
let n = coercion::to_number(self.regs[rd], self.kernel_core.string_forge().as_ref());
let result = JsValue::float(n + 1.0);