1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use std::{any::Any, borrow::Cow, collections::HashMap, rc::Rc};
use wasm_bindgen::JsValue;

use crate::PassedToJsRuntime;

#[derive(Debug, Clone, Default)]
pub struct AnyJsProps {
    pub js_props_without_children: Option<js_sys::Object>,
    pub children: Option<crate::Children>,
}

impl AnyJsPropsBuilder for AnyJsProps {
    #[inline]
    fn set_prop(&mut self, name: &str, value: &JsValue) -> &mut Self {
        let obj = self
            .js_props_without_children
            .get_or_insert_with(|| js_sys::Object::new());
        js_sys::Reflect::set(obj.as_ref(), &JsValue::from_str(name), &value).unwrap();

        self
    }

    #[inline]
    fn set_children(&mut self, children: Option<crate::Children>) -> &mut Self {
        self.children = children;
        self
    }

    #[inline]
    fn remove_prop(&mut self, name: &str) -> &mut Self {
        let obj = self
            .js_props_without_children
            .get_or_insert_with(|| js_sys::Object::new());
        js_sys::Reflect::delete_property(obj.as_ref(), &JsValue::from_str(name)).unwrap();

        self
    }
}

pub trait AnyJsPropsBuilder {
    fn set_prop(&mut self, name: &str, value: &JsValue) -> &mut Self;
    fn remove_prop(&mut self, name: &str) -> &mut Self;
    fn set_children(&mut self, children: Option<crate::Children>) -> &mut Self;
}

#[derive(Debug, Default, Clone)]
pub struct AnyJsStaticPropsPersistedValue(HashMap<Cow<'static, str>, Rc<dyn Any>>);

impl AnyJsStaticPropsPersistedValue {
    pub fn replace_static(&mut self, name: &'static str, value: Rc<dyn Any>) {
        self.0.insert(Cow::Borrowed(name), value);
    }
    pub fn replace(&mut self, name: String, value: Rc<dyn Any>) {
        self.0.insert(Cow::Owned(name), value);
    }
    pub fn remove(&mut self, name: &str) {
        self.0.remove(name);
    }
}

#[derive(Debug, Default, Clone)]
pub struct AnyJsStaticProps {
    pub props: AnyJsProps,
    pub persisted: AnyJsStaticPropsPersistedValue,
}

impl AnyJsStaticProps {
    #[inline]
    pub fn set_static_prop_and_persist(
        &mut self,
        name: &'static str,
        value: PassedToJsRuntime,
    ) -> &mut Self {
        self.props.set_prop(name, &value.js_value);
        if let Some(p) = value.to_persist {
            self.persisted.replace_static(name, p.into());
        } else {
            self.persisted.remove(name);
        }
        self
    }
}

impl AnyJsPropsBuilder for AnyJsStaticProps {
    #[inline]
    fn set_prop(&mut self, name: &str, value: &JsValue) -> &mut Self {
        self.props.set_prop(name, value);
        self.persisted.remove(name);
        self
    }

    #[inline]
    fn set_children(&mut self, children: Option<crate::Children>) -> &mut Self {
        self.props.set_children(children);
        self
    }

    fn remove_prop(&mut self, name: &str) -> &mut Self {
        self.props.remove_prop(name);
        self.persisted.remove(name);

        self
    }
}

impl crate::Props for AnyJsProps {
    type InitialBuilder = Self;

    #[inline]
    fn init_builder() -> Self::InitialBuilder {
        Default::default()
    }
}

impl crate::Props for AnyJsStaticProps {
    type InitialBuilder = Self;

    #[inline]
    fn init_builder() -> Self::InitialBuilder {
        Default::default()
    }
}

impl crate::PropsBuilder<Self> for AnyJsProps {
    #[inline]
    fn build(self) -> Self {
        self
    }
}

impl crate::PropsBuilder<Self> for AnyJsStaticProps {
    #[inline]
    fn build(self) -> Self {
        self
    }
}