Interpreter and node API: some refactoring towards being able to set properties from JS

This commit is contained in:
Olivier Goffart 2020-06-03 15:41:49 +02:00
parent fd829fc89f
commit 30d61452ba
6 changed files with 85 additions and 13 deletions

View file

@ -3,8 +3,8 @@ native = require('../native/index.node');
require.extensions['.60'] = function (module, filename) {
var c = native.load(filename);
module.exports.show = function () {
c.show();
module.exports["show"] = function () {
c.create().show();
}
}

View file

@ -15,6 +15,7 @@ name = "sixtyfps_node_native"
[dependencies]
once_cell = "1.4"
interpreter = { path="../../../sixtyfps_runtime/interpreter" }
corelib = { path="../../../sixtyfps_runtime/corelib" }
gl = { path="../../../sixtyfps_runtime/rendering_backends/gl" }
neon = "0.4"

View file

@ -1,6 +1,7 @@
use neon::prelude::*;
struct WrappedComponentType(Option<std::rc::Rc<interpreter::ComponentDescription>>);
struct WrappedComponentBox(Option<corelib::abi::datastructures::ComponentBox>);
fn load(mut cx: FunctionContext) -> JsResult<JsValue> {
let path = cx.argument::<JsString>(0)?.value();
@ -19,10 +20,17 @@ fn load(mut cx: FunctionContext) -> JsResult<JsValue> {
Ok(obj.as_value(&mut cx))
}
fn show(ct: std::rc::Rc<interpreter::ComponentDescription>) {
let component = interpreter::instentiate(ct);
// FIXME: leak (that's because we somehow need a static life time)
gl::sixtyfps_runtime_run_component_with_gl_renderer(component.leak())
fn create<'cx>(
cx: &mut CallContext<'cx, impl neon::object::This>,
component_type: std::rc::Rc<interpreter::ComponentDescription>,
) -> JsResult<'cx, JsValue> {
let component = component_type.create();
//component_type.set_property(component, name, value);
let mut obj = SixtyFpsComponent::new::<_, JsValue, _>(cx, std::iter::empty())?;
cx.borrow_mut(&mut obj, |mut obj| obj.0 = Some(component));
Ok(obj.as_value(cx))
}
declare_types! {
@ -30,13 +38,26 @@ declare_types! {
init(_) {
Ok(WrappedComponentType(None))
}
method show(mut cx) {
method create(mut cx) {
let this = cx.this();
let ct = cx.borrow(&this, |x| x.0.clone());
let ct = ct.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
show(ct);
Ok(cx.undefined().as_value(&mut cx))
create(&mut cx, ct)
}
}
class SixtyFpsComponent for WrappedComponentBox {
init(_) {
Ok(WrappedComponentBox(None))
}
method show(mut cx) {
let mut this = cx.this();
// FIXME: is take() here the right choice?
let component = cx.borrow_mut(&mut this, |mut x| x.0.take());
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
gl::sixtyfps_runtime_run_component_with_gl_renderer(component.leak());
// FIXME: leak (that's because we somehow need a static life time)
Ok(JsUndefined::new().as_value(&mut cx))
}
}
}

View file

@ -37,7 +37,7 @@ pub struct ComponentImpl {
#[repr(C)]
pub struct MyComponentType {
ct: ComponentVTable,
pub(crate) ct: ComponentVTable,
dynamic_type: Rc<dynamic_type::TypeInfo>,
it: Vec<corelib::abi::datastructures::ItemTreeNode>,
pub(crate) items: HashMap<String, ItemWithinComponent>,

View file

@ -2,9 +2,13 @@ mod dynamic_component;
mod dynamic_type;
mod eval;
pub(crate) use dynamic_component::ComponentImpl;
pub use dynamic_component::load;
pub use dynamic_component::MyComponentType as ComponentDescription;
pub use dynamic_component::{instentiate, load};
pub use eval::Value;
use corelib::abi::datastructures::{ComponentBox, ComponentRef, ComponentRefMut};
pub(crate) use dynamic_component::ComponentImpl;
use std::rc::Rc;
impl ComponentDescription {
/// The name of this Component as written in the .60 file
@ -23,4 +27,50 @@ impl ComponentDescription {
.map(|(s, v)| (s.clone(), v.property_type.clone()))
.collect()
}
pub fn create(self: Rc<Self>) -> ComponentBox {
dynamic_component::instentiate(self)
}
pub fn set_property(
&self,
component: ComponentRef,
name: &str,
value: Value,
) -> Result<(), ()> {
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
return Err(());
}
let x = self.custom_properties.get(name).ok_or(())?;
unsafe { x.prop.set(&*component.as_ptr().add(x.offset), value) }
}
pub fn set_binding(
&self,
component: ComponentRef,
name: &str,
binding: Box<dyn Fn(&corelib::EvaluationContext) -> Value>,
) -> Result<(), ()> {
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
return Err(());
}
let x = self.custom_properties.get(name).ok_or(())?;
unsafe { x.prop.set_binding(&*component.as_ptr().add(x.offset), binding) };
Ok(())
}
pub fn set_signal(
&self,
component: ComponentRefMut,
name: &str,
handler: Box<dyn Fn(&corelib::EvaluationContext, ())>,
) -> Result<(), ()> {
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
return Err(());
}
let x = self.custom_signals.get(name).ok_or(())?;
let sig = unsafe { &mut *(component.as_ptr().add(*x) as *mut corelib::Signal<()>) };
sig.set_handler(handler);
Ok(())
}
}

View file

@ -17,7 +17,7 @@ fn main() -> std::io::Result<()> {
}
};
let component = interpreter::instentiate(c);
let component = c.create();
gl::sixtyfps_runtime_run_component_with_gl_renderer(component.leak());
Ok(())
}