feat: 支持内建函数调用并修复初始化与绑定问题

This commit is contained in:
爱特每羊队
2026-06-07 11:32:25 +08:00
parent e2d5893205
commit 52fbd3c3d4
5 changed files with 381 additions and 86 deletions
+152
View File
@@ -0,0 +1,152 @@
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::JsObject;
use oxide_types::value::JsValue;
use crate::native::{NativeFn, NativeResult};
use crate::vm::Vm;
fn invoke_target(
vm: &mut Vm,
target_val: JsValue,
this_val: JsValue,
arg_regs: &[u8],
) -> NativeResult {
if !target_val.is_object() {
return Err(JsValue::undefined());
}
let tgt_ptr = target_val.as_js_object_ptr();
if tgt_ptr.is_null() {
return Err(JsValue::undefined());
}
let tgt = unsafe { &*tgt_ptr };
if !tgt.is_function() || tgt.native_fn().is_none() {
return Err(JsValue::undefined());
}
let func: NativeFn = unsafe { std::mem::transmute(tgt.native_fn().unwrap()) };
let base = 230u8;
let n = arg_regs.len();
let mut args_buf = [0u8; 64];
args_buf[0] = base;
vm.set_reg(base, this_val);
for (i, &reg) in arg_regs.iter().enumerate().take(n.min(63)) {
vm.set_reg(base + 1 + i as u8, vm.reg(reg));
args_buf[i + 1] = base + 1 + i as u8;
}
func(vm, &args_buf[..n + 1])
}
fn bind_dispatcher(vm: &mut Vm, args: &[u8]) -> NativeResult {
let wrapper_val = vm.reg(254);
let wrapper = unsafe { &*wrapper_val.as_js_object_ptr() };
let bound_target = wrapper.get_prop(0);
let bound_this = wrapper.get_prop(1);
let n = args.len().saturating_sub(1);
let base = 230u8;
let mut args_buf = [0u8; 64];
args_buf[0] = base;
vm.set_reg(base, bound_this);
for (i, &reg) in args.iter().skip(1).enumerate().take(n.min(63)) {
vm.set_reg(base + 1 + i as u8, vm.reg(reg));
args_buf[i + 1] = base + 1 + i as u8;
}
if !bound_target.is_object() {
return Err(JsValue::undefined());
}
let tgt_ptr = bound_target.as_js_object_ptr();
if tgt_ptr.is_null() {
return Err(JsValue::undefined());
}
let tgt = unsafe { &*tgt_ptr };
if !tgt.is_function() || tgt.native_fn().is_none() {
return Err(JsValue::undefined());
}
let func: NativeFn = unsafe { std::mem::transmute(tgt.native_fn().unwrap()) };
func(vm, &args_buf[..n + 1])
}
pub fn function_call(vm: &mut Vm, args: &[u8]) -> NativeResult {
if args.is_empty() {
return Err(JsValue::undefined());
}
let target_val = vm.reg(args[0]);
let this_val = if args.len() > 1 {
vm.reg(args[1])
} else {
JsValue::undefined()
};
let arg_regs: Vec<u8> = args.iter().skip(2).copied().collect();
invoke_target(vm, target_val, this_val, &arg_regs)
}
pub fn function_apply(vm: &mut Vm, args: &[u8]) -> NativeResult {
if args.is_empty() {
return Err(JsValue::undefined());
}
let target_val = vm.reg(args[0]);
let this_val = if args.len() > 1 {
vm.reg(args[1])
} else {
JsValue::undefined()
};
let arg_regs: Vec<u8>;
if args.len() > 2 {
let arr_val = vm.reg(args[2]);
if arr_val.is_object() {
let arr_ptr = arr_val.as_js_object_ptr();
if !arr_ptr.is_null() {
let arr = unsafe { &*arr_ptr };
if arr.is_array() {
let n = arr.prop_count() as usize;
let base = 200u8;
arg_regs = (0..n).map(|i| base + i as u8).collect();
for i in 0..n {
vm.set_reg(base + i as u8, arr.get_prop(i as u8));
}
} else {
arg_regs = Vec::new();
}
} else {
arg_regs = Vec::new();
}
} else {
arg_regs = Vec::new();
}
} else {
arg_regs = Vec::new();
}
invoke_target(vm, target_val, this_val, &arg_regs)
}
pub fn function_bind(vm: &mut Vm, args: &[u8]) -> NativeResult {
if args.is_empty() {
return Err(JsValue::undefined());
}
let target_val = vm.reg(args[0]);
if !target_val.is_object() {
return Err(JsValue::undefined());
}
let bound_this = if args.len() > 1 {
vm.reg(args[1])
} else {
JsValue::undefined()
};
let wrapper = vm
.epoch()
.alloc(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
unsafe {
(*wrapper).set_function(true);
(*wrapper).set_native_fn(Some(bind_dispatcher as *const ()));
(*wrapper).set_native_arg_count(0);
(*wrapper).set_prop_count(2);
(*wrapper).set_inline_prop(0, target_val);
(*wrapper).set_inline_prop(1, bound_this);
}
Ok(JsValue::from_js_object(wrapper))
}
+1
View File
@@ -1,5 +1,6 @@
pub mod array;
pub mod error;
pub mod function;
pub mod global;
pub mod math;
pub mod number;
+43 -31
View File
@@ -9,7 +9,7 @@ use oxide_compiler::opcode::{self, OpCode};
use crate::coercion;
use crate::native::NativeFn;
use oxide_kernel::builtin::{
ArrayMethods, ErrorMethods, NumberMethods, ObjectMethods, StringMethods,
ArrayMethods, ErrorMethods, FunctionMethods, NumberMethods, ObjectMethods, StringMethods,
};
use oxide_kernel::kernel::{KernelConfig, OxideKernel};
use oxide_kernel::prop_forge::PropTemplate;
@@ -206,7 +206,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
let pi_fn = crate::builtins::number::number_parse_int as *const ();
let pf_fn = crate::builtins::number::number_parse_float as *const ();
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
global,
kernel.shape_forge().as_ref(),
kernel.string_forge().as_ref(),
@@ -214,7 +214,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
pi_fn,
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
global,
kernel.shape_forge().as_ref(),
kernel.string_forge().as_ref(),
@@ -228,7 +228,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
let sf = kernel.string_forge().as_ref();
let sh = kernel.shape_forge().as_ref();
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -236,7 +236,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_abs as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -244,7 +244,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_acos as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -252,7 +252,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_asin as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -260,7 +260,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_atan as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -268,7 +268,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_atan2 as *const (),
2,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -276,7 +276,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_cbrt as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -284,7 +284,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_ceil as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -292,7 +292,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_cos as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -300,7 +300,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_cosh as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -308,7 +308,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_exp as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -316,7 +316,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_floor as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -324,7 +324,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_hypot as *const (),
2,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -332,7 +332,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_imul as *const (),
2,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -340,7 +340,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_log as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -348,7 +348,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_log10 as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -356,7 +356,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_log2 as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -364,7 +364,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_max as *const (),
2,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -372,7 +372,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_min as *const (),
2,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -380,7 +380,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_pow as *const (),
2,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -388,7 +388,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_random as *const (),
0,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -396,7 +396,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_round as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -404,7 +404,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_sign as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -412,7 +412,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_sin as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -420,7 +420,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_sinh as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -428,7 +428,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_sqrt as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -436,7 +436,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_tan as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -444,7 +444,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
crate::builtins::math::math_tanh as *const (),
1,
);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
let _ = kernel.builtin_world().bind_method(
math,
sh,
sf,
@@ -472,6 +472,17 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
global.set_prop_count(cur_count + 1);
global.set_prop_expand_heap(cur_count, m_val);
global.bump_generation();
let function_methods = FunctionMethods {
call: crate::builtins::function::function_call as *const (),
apply: crate::builtins::function::function_apply as *const (),
bind: crate::builtins::function::function_bind as *const (),
};
kernel.builtin_world().bind_function_methods(
&function_methods,
kernel.string_forge().as_ref(),
kernel.shape_forge().as_ref(),
);
}
impl Vm {
@@ -887,6 +898,7 @@ impl Vm {
let func: NativeFn =
unsafe { std::mem::transmute(obj.native_fn().unwrap()) };
self.regs[254] = callee;
match func(self, args_slice) {
Ok(val) => self.regs[0] = val,
Err(err_val) => {