Added dynatos::ObjectAttachContext.

This commit is contained in:
Filipe Rodrigues 2024-02-19 04:22:39 +00:00
parent 38cb0ca46c
commit 9ca824015f
Signed by: zenithsiz
SSH Key Fingerprint: SHA256:Mb5ppb3Sh7IarBO/sBTXLHbYEOz37hJAlslLQPPAPaU
7 changed files with 59 additions and 23 deletions

1
Cargo.lock generated
View File

@ -35,6 +35,7 @@ name = "dynatos"
version = "0.1.0"
dependencies = [
"duplicate",
"dynatos-context",
"dynatos-html",
"dynatos-reactive",
"dynatos-util",

View File

@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
dynatos-context = { workspace = true }
dynatos-html = { workspace = true }
dynatos-reactive = { workspace = true }
dynatos-util = { workspace = true }

View File

@ -7,6 +7,7 @@
mod element_dyn_attr;
mod node_dyn_child;
mod node_dyn_text;
mod object_attach_context;
mod object_attach_effect;
mod object_dyn_prop;
@ -15,6 +16,7 @@ pub use self::{
element_dyn_attr::ElementDynAttr,
node_dyn_child::{NodeDynChild, ToDynNode},
node_dyn_text::{NodeDynText, WithDynText},
object_attach_context::ObjectAttachContext,
object_attach_effect::ObjectAttachEffect,
object_dyn_prop::ObjectDynProp,
};

View File

@ -0,0 +1,49 @@
//! Object context attaching
// Imports
use {
dynatos_context::OpaqueHandle,
dynatos_util::{ObjectGet, ObjectSetProp},
wasm_bindgen::prelude::wasm_bindgen,
};
/// Extension trait to add an context to an object
// TODO: Allow removing context handles?
#[extend::ext(name = ObjectAttachContext)]
pub impl<T> T
where
T: AsRef<js_sys::Object>,
{
/// Provides and attaches a context to this object
fn attach_context<U: 'static>(&self, value: U) {
// Get the context handles array, or create it, if it doesn't exist
// TODO: Use an static anonymous symbol?
let prop_name: &str = "__dynatos_ctx_handles";
let obj = self.as_ref();
let ctx_handles = match obj.get::<js_sys::Array>(prop_name) {
Ok(ctx_handles) => ctx_handles,
Err(dynatos_util::GetError::WrongType(err)) => panic!("Contexts array was the wrong type: {err:?}"),
Err(dynatos_util::GetError::Missing) => {
let ctx_handles = js_sys::Array::new();
obj.set_prop(prop_name, &ctx_handles);
ctx_handles
},
};
// Then push the context handle
let handle = dynatos_context::provide::<U>(value).into_opaque();
let handle = WasmContextHandle(handle);
ctx_handles.push(&handle.into());
}
/// Provides and attaches a context to this object
fn with_context<U: 'static>(self, value: U) -> Self {
self.attach_context(value);
self
}
}
/// A wasm `OpaqueHandle` type.
#[wasm_bindgen]
#[expect(dead_code, reason = "We just want to keep the field alive, not use it")]
struct WasmContextHandle(OpaqueHandle);

1
examples/Cargo.lock generated
View File

@ -63,6 +63,7 @@ name = "dynatos"
version = "0.1.0"
dependencies = [
"duplicate",
"dynatos-context",
"dynatos-html",
"dynatos-reactive",
"dynatos-util",

View File

@ -5,14 +5,12 @@
// Imports
use {
dynatos::NodeDynText,
dynatos_context::Handle,
dynatos::{NodeDynText, ObjectAttachContext},
dynatos_html::{html, NodeWithChildren, NodeWithText},
dynatos_reactive::{SignalGet, SignalSet, SignalUpdate, SignalWithDefault},
dynatos_router::{Location, QuerySignal},
dynatos_util::{ev, EventTargetWithListener, ObjectSetProp},
dynatos_util::{ev, EventTargetWithListener},
tracing_subscriber::prelude::*,
wasm_bindgen::prelude::wasm_bindgen,
web_sys::Element,
};
@ -40,15 +38,8 @@ fn run() -> Result<(), anyhow::Error> {
let body = document.body().expect("Unable to get document body");
let location = Location::new();
let location_handle = dynatos_context::provide(location);
let child = self::page();
body.append_child(&child).expect("Unable to append child");
#[wasm_bindgen]
#[expect(dead_code, reason = "We just want to keep the field alive, not use it")]
struct LocationHandle(Handle<Location>);
body.set_prop("__dynatos_location_handle", LocationHandle(location_handle));
body.with_context::<Location>(location).with_child(self::page());
Ok(())
}

View File

@ -5,15 +5,12 @@
// Imports
use {
dynatos::NodeDynChild,
dynatos_context::Handle,
dynatos::{NodeDynChild, ObjectAttachContext},
dynatos_html::{html, NodeWithChildren, NodeWithText},
dynatos_reactive::SignalGet,
dynatos_router::Location,
dynatos_util::ObjectSetProp,
std::cell::LazyCell,
tracing_subscriber::prelude::*,
wasm_bindgen::prelude::wasm_bindgen,
web_sys::Element,
};
@ -41,9 +38,8 @@ fn run() -> Result<(), anyhow::Error> {
let body = document.body().expect("Unable to get document body");
let location = Location::new();
let location_handle = dynatos_context::provide(location);
(&body).with_child(
body.with_context(location).with_child(
html::div()
.with_children([html::p().with_text("Header"), html::hr()])
.with_dyn_child(self::render_route)
@ -57,11 +53,6 @@ fn run() -> Result<(), anyhow::Error> {
]),
);
#[wasm_bindgen]
#[expect(dead_code, reason = "We just want to keep the field alive, not use it")]
struct LocationHandle(Handle<Location>);
body.set_prop("__dynatos_location_handle", LocationHandle(location_handle));
Ok(())
}