Validate unified source and native positional call contracts

This commit is contained in:
2026-10-22 12:02:41 +08:00
parent 20e29e3c5a
commit 44519abf7e
17 changed files with 331 additions and 28 deletions
+17
View File
@@ -117,6 +117,11 @@ pub trait ObjectPayload: Any + fmt::Debug + Send + Sync {
/// Host-call entry: arguments and raw results are borrowed handles. The VM
/// validates/retains the result before exposing it as an owned call result.
/// Language functions are dispatched by Vm's frame evaluator instead.
/// Positional metadata for native call protocols; source code is queried by the store.
fn call_arity(&self) -> Option<crate::CallArity> {
self.native_callable().and_then(|callable| callable.arity())
}
fn call(&self, _arguments: &[Value]) -> Result<Value, VmError> {
Err(VmError::UnsupportedOperation("call"))
}
@@ -176,6 +181,7 @@ pub type NativeCall = EndorNativeCall;
pub struct EndorNativeFunctionObject {
name: String,
function: NativeCall,
arity: Option<crate::CallArity>,
}
impl EndorNativeFunctionObject {
@@ -183,12 +189,17 @@ impl EndorNativeFunctionObject {
Self {
name: name.into(),
function,
arity: None,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn with_arity(mut self, arity: crate::CallArity) -> Self {
self.arity = Some(arity);
self
}
}
/// Compatibility name for existing embedders.
@@ -213,7 +224,13 @@ impl ObjectPayload for EndorNativeFunctionObject {
Ok(format!("<native-function {}>", self.name))
}
fn call_arity(&self) -> Option<crate::CallArity> {
self.arity
}
fn call(&self, arguments: &[Value]) -> Result<Value, VmError> {
if let Some(arity) = self.arity {
arity.check(self.name.clone(), arguments.len())?;
}
(self.function)(arguments)
}
}