#![deny(rust_2018_idioms)]
#![feature(try_trait_v2)]
mod computed;
mod css;
mod dom_list;
mod dom_value;
mod dom;
mod driver_module;
mod fetch;
mod future_box;
mod html_macro;
pub mod inspect;
mod instant;
pub mod router;
mod websocket;
mod external_api;
use computed::struct_mut::ValueMut;
pub use computed::{
AutoMap, Client, Computed, context::Context, Dependencies, DropResource, GraphId, struct_mut, Value
};
pub(crate) use dom::dom_comment::DomComment;
pub use dom::{
css::{Css, CssGroup},
dom_id::DomId,
dom_fragment::DomFragment,
dom_element::DomElement,
dom_node::DomNode,
dom_text::DomText,
types::{KeyDownEvent, DropFileEvent, DropFileItem},
};
pub use dom_list::ListRendered;
use driver_module::{init_env::init_env, api::CallbackId};
pub use driver_module::{
api::ApiImport,
driver::{Driver, FetchResult, FetchMethod},
js_value::{
MemoryBlock,
JsValue,
JsJson,
JsJsonSerialize,
JsJsonDeserialize,
JsJsonContext,
JsJsonObjectBuilder,
from_json,
to_json
},
dom_command::DriverDomCommand,
};
pub use fetch::{
lazy_cache::{self, LazyCache},
pinboxfut::PinBoxFuture,
request_builder::{RequestResponse, RequestBuilder, RequestBody},
resource::Resource,
};
pub use future_box::{FutureBoxSend, FutureBox};
pub use html_macro::{
EmbedDom
};
pub use instant::{
Instant, InstantType
};
pub use websocket::{WebsocketConnection, WebsocketMessage};
pub use vertigo_macro::include_static;
pub use vertigo_macro::bind;
pub use vertigo_macro::bind_rc;
pub use vertigo_macro::bind_spawn;
pub use vertigo_macro::AutoJsJson;
pub use vertigo_macro::component;
pub use log;
pub use vertigo_macro::dom;
pub use vertigo_macro::dom_debug;
pub use vertigo_macro::css;
pub use vertigo_macro::css_block;
pub mod html_entities;
pub struct DriverConstruct {
driver: Driver,
subscription: ValueMut<Option<DomElement>>,
}
impl DriverConstruct {
fn new() -> DriverConstruct {
let driver = Driver::default();
DriverConstruct {
driver,
subscription: ValueMut::new(None),
}
}
fn set_root(&self, root_view: DomElement) {
self.subscription.set(Some(root_view));
}
}
thread_local! {
static DRIVER_BROWSER: DriverConstruct = DriverConstruct::new();
}
fn start_app_inner(root_view: DomElement) {
get_driver_state("start_app", |state| {
init_env(state.driver.inner.api.clone());
state.driver.inner.api.on_fetch_start.trigger(());
state.set_root(root_view);
state.driver.inner.api.on_fetch_stop.trigger(());
get_driver().inner.dom.flush_dom_changes();
});
}
pub fn start_app(init_app: fn() -> DomElement) {
get_driver_state("start_app", |state| {
init_env(state.driver.inner.api.clone());
let dom = init_app();
start_app_inner(dom);
});
}
pub fn get_driver() -> Driver {
DRIVER_BROWSER.with(|state| {
state.driver.clone()
})
}
pub fn transaction<R, F: FnOnce(&Context) -> R>(f: F) -> R {
get_driver().transaction(f)
}
fn get_driver_state<R: Default, F: FnOnce(&DriverConstruct) -> R>(label: &'static str, once: F) -> R {
match DRIVER_BROWSER.try_with(once) {
Ok(value) => value,
Err(_) => {
if label != "free" {
println!("error access {label}");
}
R::default()
}
}
}
#[no_mangle]
pub fn alloc(size: u32) -> u32 {
get_driver_state("alloc", |state| {
state.driver.inner.api.arguments.alloc(size)
})
}
#[no_mangle]
pub fn free(pointer: u32) {
get_driver_state("free", |state| {
state.driver.inner.api.arguments.free(pointer);
})
}
#[no_mangle]
pub fn wasm_callback(callback_id: u64, value_ptr: u32) -> u64 {
get_driver_state("export_dom_callback", |state| {
let value = state.driver.inner.api.arguments.get_by_ptr(value_ptr);
let callback_id = CallbackId::from_u64(callback_id);
let mut result = JsValue::Undefined;
state.driver.transaction(|_| {
result = state.driver.inner.api.callback_store.call(callback_id, value);
});
if result == JsValue::Undefined {
return 0;
}
let memory_block = result.to_snapshot();
let (ptr, size) = memory_block.get_ptr_and_size();
state.driver.inner.api.arguments.set(memory_block);
let ptr = ptr as u64;
let size = size as u64;
(ptr << 32) + size
})
}