diff --git a/api/sixtyfps-node/lib/index.js b/api/sixtyfps-node/lib/index.js index d0408ff74..1263703c5 100644 --- a/api/sixtyfps-node/lib/index.js +++ b/api/sixtyfps-node/lib/index.js @@ -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(); } } diff --git a/api/sixtyfps-node/native/Cargo.toml b/api/sixtyfps-node/native/Cargo.toml index b50670423..dab4df080 100644 --- a/api/sixtyfps-node/native/Cargo.toml +++ b/api/sixtyfps-node/native/Cargo.toml @@ -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" diff --git a/api/sixtyfps-node/native/lib.rs b/api/sixtyfps-node/native/lib.rs index 595331724..25e97b9db 100644 --- a/api/sixtyfps-node/native/lib.rs +++ b/api/sixtyfps-node/native/lib.rs @@ -1,6 +1,7 @@ use neon::prelude::*; struct WrappedComponentType(Option>); +struct WrappedComponentBox(Option); fn load(mut cx: FunctionContext) -> JsResult { let path = cx.argument::(0)?.value(); @@ -19,10 +20,17 @@ fn load(mut cx: FunctionContext) -> JsResult { Ok(obj.as_value(&mut cx)) } -fn show(ct: std::rc::Rc) { - 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, +) -> 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)) } } } diff --git a/sixtyfps_runtime/interpreter/dynamic_component.rs b/sixtyfps_runtime/interpreter/dynamic_component.rs index 6cc03982e..6f474f4ae 100644 --- a/sixtyfps_runtime/interpreter/dynamic_component.rs +++ b/sixtyfps_runtime/interpreter/dynamic_component.rs @@ -37,7 +37,7 @@ pub struct ComponentImpl { #[repr(C)] pub struct MyComponentType { - ct: ComponentVTable, + pub(crate) ct: ComponentVTable, dynamic_type: Rc, it: Vec, pub(crate) items: HashMap, diff --git a/sixtyfps_runtime/interpreter/lib.rs b/sixtyfps_runtime/interpreter/lib.rs index e23450cf1..6c8e2983f 100644 --- a/sixtyfps_runtime/interpreter/lib.rs +++ b/sixtyfps_runtime/interpreter/lib.rs @@ -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) -> 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 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, + ) -> 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(()) + } } diff --git a/tools/viewer/main.rs b/tools/viewer/main.rs index 2d78569b5..562240654 100644 --- a/tools/viewer/main.rs +++ b/tools/viewer/main.rs @@ -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(()) }