91 lines
3.3 KiB
Rust
91 lines
3.3 KiB
Rust
//! Host capability definitions over Aster's explicit managed trait relations.
|
|
use endor_core::{
|
|
AnnotationType, CallArity, CallEffect, CallSignature, ObjectRef, TypedMethodRequirement, Value,
|
|
Vm, VmError,
|
|
};
|
|
|
|
pub fn install(
|
|
vm: &mut Vm,
|
|
roots: &mut Vec<ObjectRef>,
|
|
desktop: ObjectRef,
|
|
ui: ObjectRef,
|
|
) -> Result<(), VmError> {
|
|
let Value::Object(trait_type) = vm.get_attr(ui, "Trait")? else {
|
|
return Err(VmError::InvalidArgument("missing Trait type"));
|
|
};
|
|
let Value::Object(types) = vm.get_attr(desktop, "types")? else {
|
|
return Err(VmError::InvalidArgument("missing type registry"));
|
|
};
|
|
for (name, methods, owner) in [
|
|
(
|
|
"Visual",
|
|
vec![("measure", 2), ("arrange", 2), ("paint", 2), ("hitTest", 2)],
|
|
Some("Block"),
|
|
),
|
|
(
|
|
"EventTarget",
|
|
vec![("on", 3), ("dispatch", 2), ("onEvent", 1)],
|
|
Some("Block"),
|
|
),
|
|
(
|
|
"Children",
|
|
vec![
|
|
("append", 1),
|
|
("insert", 2),
|
|
("remove", 1),
|
|
("replace", 2),
|
|
("move", 2),
|
|
("children", 0),
|
|
],
|
|
Some("ContainerBlock"),
|
|
),
|
|
("Presentable", vec![("present", 1)], None),
|
|
] {
|
|
let owner_definition = if let Some(owner) = owner {
|
|
let Value::Object(definition) = vm.get_attr(ui, owner)? else {
|
|
return Err(VmError::InvalidArgument("missing protocol owner"));
|
|
};
|
|
Some(definition)
|
|
} else {
|
|
None
|
|
};
|
|
let mut requirements = Vec::new();
|
|
for (method, parameters) in methods {
|
|
let mut signature = if let Some(owner) = owner_definition {
|
|
let function = vm
|
|
.object_store()
|
|
.lookup_method(owner, method)?
|
|
.ok_or(VmError::InvalidArgument("missing protocol method"))?;
|
|
vm.object_store()
|
|
.native_signature(function)?
|
|
.ok_or(VmError::InvalidArgument(
|
|
"protocol method lacks native types",
|
|
))?
|
|
} else {
|
|
let window = crate::ui_bridge::desktop_type(vm.object_store(), "Window", desktop)?;
|
|
let block = crate::ui_bridge::desktop_type(vm.object_store(), "Block", desktop)?;
|
|
CallSignature::exact(
|
|
vec![AnnotationType::Any, AnnotationType::Nominal(window)],
|
|
AnnotationType::Nominal(block),
|
|
CallEffect::External,
|
|
)
|
|
};
|
|
signature.arity = CallArity::exact(parameters + 1);
|
|
signature.parameters[0] = AnnotationType::Any.into();
|
|
requirements.push(TypedMethodRequirement {
|
|
name: method.into(),
|
|
signature,
|
|
});
|
|
}
|
|
let capability = vm.new_typed_trait(name, requirements)?;
|
|
roots.push(capability);
|
|
vm.attach_type(capability, trait_type)?;
|
|
vm.set_attr(ui, name, Value::Object(capability))?;
|
|
vm.dict_set(types, Value::Text(name.into()), Value::Object(capability))?;
|
|
if let Some(owner) = owner_definition {
|
|
vm.implement_trait(owner, capability)?;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|