wip: more work on web
this commit adds complete event support for web-sys but with a few hole
This commit is contained in:
1 parent
59219b9ef2
commit
3bf19d8106
13 files changed
+709
-355
No files matched your search
+10
-10
@@ -90,17 +90,17 @@ impl SharedResources {
|
||||
let comps = unsafe { &*components.get() };
|
||||
|
||||
if let Some(scope) = comps.get(idx.0) {
|
||||
todo!("implement immediates again")
|
||||
// todo!("implement immediates again")
|
||||
//
|
||||
|
||||
// queue
|
||||
// .unbounded_send(EventTrigger::new(
|
||||
// VirtualEvent::ScheduledUpdate {
|
||||
// height: scope.height,
|
||||
// },
|
||||
// idx,
|
||||
// None,
|
||||
// EventPriority::High,
|
||||
// ))
|
||||
// .expect("The event queu receiver should *never* be dropped");
|
||||
// .unbounded_send(EventTrigger::new(
|
||||
// V
|
||||
// idx,
|
||||
// None,
|
||||
// EventPriority::High,
|
||||
// ))
|
||||
// .expect("The event queu receiver should *never* be dropped");
|
||||
}
|
||||
}) as Rc<dyn Fn(ScopeId)>
|
||||
};
|
||||
|
||||
@@ -138,14 +138,12 @@ impl<'bump> DiffMachine<'bump> {
|
||||
}
|
||||
|
||||
//
|
||||
pub async fn diff_scope(&mut self, id: ScopeId) -> Result<()> {
|
||||
let component = self
|
||||
.vdom
|
||||
.get_scope_mut(id)
|
||||
.ok_or_else(|| Error::NotMounted)?;
|
||||
let (old, new) = (component.frames.wip_head(), component.frames.fin_head());
|
||||
self.diff_node(old, new);
|
||||
Ok(())
|
||||
pub async fn diff_scope(&mut self, id: ScopeId) {
|
||||
if let Some(component) = self.vdom.get_scope_mut(id) {
|
||||
let (old, new) = (component.frames.wip_head(), component.frames.fin_head());
|
||||
self.stack.push(DiffInstruction::DiffNode { new, old });
|
||||
self.work().await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Progress the diffing for this "fiber"
|
||||
|
||||
+25
-18
@@ -153,6 +153,7 @@ pub enum VirtualEvent {
|
||||
MouseEvent(on::MouseEvent),
|
||||
PointerEvent(on::PointerEvent),
|
||||
}
|
||||
|
||||
impl VirtualEvent {
|
||||
pub fn is_input_event(&self) -> bool {
|
||||
match self {
|
||||
@@ -215,7 +216,7 @@ pub mod on {
|
||||
|
||||
#![allow(unused)]
|
||||
use bumpalo::boxed::Box as BumpBox;
|
||||
use std::{cell::RefCell, fmt::Debug, ops::Deref, rc::Rc};
|
||||
use std::{any::Any, cell::RefCell, fmt::Debug, ops::Deref, rc::Rc};
|
||||
|
||||
use crate::{
|
||||
innerlude::NodeFactory,
|
||||
@@ -563,6 +564,8 @@ pub mod on {
|
||||
}
|
||||
|
||||
pub trait GenericEventInner {
|
||||
/// Return a reference to the raw event. User will need to downcast the event to the right platform-specific type.
|
||||
fn raw_event(&self) -> &dyn Any;
|
||||
/// Returns whether or not a specific event is a bubbling event
|
||||
fn bubbles(&self) -> bool;
|
||||
/// Sets or returns whether the event should propagate up the hierarchy or not
|
||||
@@ -571,14 +574,18 @@ pub mod on {
|
||||
fn cancelable(&self) -> bool;
|
||||
/// Returns whether the event is composed or not
|
||||
fn composed(&self) -> bool;
|
||||
/// Returns the event's path
|
||||
fn composed_path(&self) -> String;
|
||||
|
||||
// Currently not supported because those no way we could possibly support it
|
||||
// just cast the event to the right platform-specific type and return it
|
||||
// /// Returns the event's path
|
||||
// fn composed_path(&self) -> String;
|
||||
|
||||
/// Returns the element whose event listeners triggered the event
|
||||
fn current_target(&self);
|
||||
/// Returns whether or not the preventDefault method was called for the event
|
||||
fn default_prevented(&self) -> bool;
|
||||
/// Returns which phase of the event flow is currently being evaluated
|
||||
fn event_phase(&self) -> usize;
|
||||
fn event_phase(&self) -> u16;
|
||||
/// Returns whether or not an event is trusted
|
||||
fn is_trusted(&self) -> bool;
|
||||
/// Cancels the event if it is cancelable, meaning that the default action that belongs to the event will
|
||||
@@ -590,7 +597,7 @@ pub mod on {
|
||||
/// Returns the element that triggered the event
|
||||
fn target(&self);
|
||||
/// Returns the time (in milliseconds relative to the epoch) at which the event was created
|
||||
fn time_stamp(&self) -> usize;
|
||||
fn time_stamp(&self) -> f64;
|
||||
}
|
||||
|
||||
pub trait ClipboardEventInner {
|
||||
@@ -688,8 +695,8 @@ pub mod on {
|
||||
pub trait PointerEventInner {
|
||||
// Mouse only
|
||||
fn alt_key(&self) -> bool;
|
||||
fn button(&self) -> usize;
|
||||
fn buttons(&self) -> usize;
|
||||
fn button(&self) -> i16;
|
||||
fn buttons(&self) -> u16;
|
||||
fn client_x(&self) -> i32;
|
||||
fn client_y(&self) -> i32;
|
||||
fn ctrl_key(&self) -> bool;
|
||||
@@ -699,12 +706,12 @@ pub mod on {
|
||||
fn screen_x(&self) -> i32;
|
||||
fn screen_y(&self) -> i32;
|
||||
fn shift_key(&self) -> bool;
|
||||
fn get_modifier_state(&self, key_code: usize) -> bool;
|
||||
fn pointer_id(&self) -> usize;
|
||||
fn width(&self) -> usize;
|
||||
fn height(&self) -> usize;
|
||||
fn pressure(&self) -> usize;
|
||||
fn tangential_pressure(&self) -> usize;
|
||||
fn get_modifier_state(&self, key_code: &str) -> bool;
|
||||
fn pointer_id(&self) -> i32;
|
||||
fn width(&self) -> i32;
|
||||
fn height(&self) -> i32;
|
||||
fn pressure(&self) -> f32;
|
||||
fn tangential_pressure(&self) -> f32;
|
||||
fn tilt_x(&self) -> i32;
|
||||
fn tilt_y(&self) -> i32;
|
||||
fn twist(&self) -> i32;
|
||||
@@ -719,7 +726,7 @@ pub mod on {
|
||||
fn ctrl_key(&self) -> bool;
|
||||
fn meta_key(&self) -> bool;
|
||||
fn shift_key(&self) -> bool;
|
||||
fn get_modifier_state(&self, key_code: usize) -> bool;
|
||||
fn get_modifier_state(&self, key_code: &str) -> bool;
|
||||
// changedTouches: DOMTouchList,
|
||||
// targetTouches: DOMTouchList,
|
||||
// touches: DOMTouchList,
|
||||
@@ -731,10 +738,10 @@ pub mod on {
|
||||
}
|
||||
|
||||
pub trait WheelEventInner {
|
||||
fn delta_mode(&self) -> i32;
|
||||
fn delta_x(&self) -> i32;
|
||||
fn delta_y(&self) -> i32;
|
||||
fn delta_z(&self) -> i32;
|
||||
fn delta_mode(&self) -> u32;
|
||||
fn delta_x(&self) -> f64;
|
||||
fn delta_y(&self) -> f64;
|
||||
fn delta_z(&self) -> f64;
|
||||
}
|
||||
|
||||
pub trait MediaEventInner {}
|
||||
|
||||
@@ -50,15 +50,13 @@ pub struct Scheduler {
|
||||
|
||||
shared: SharedResources,
|
||||
|
||||
waypoints: VecDeque<Waypoint>,
|
||||
|
||||
high_priorty: PriortySystem,
|
||||
medium_priority: PriortySystem,
|
||||
low_priority: PriortySystem,
|
||||
}
|
||||
|
||||
pub enum FiberResult<'a> {
|
||||
Done(&'a mut Mutations<'a>),
|
||||
Done(Mutations<'a>),
|
||||
Interrupted,
|
||||
}
|
||||
|
||||
@@ -75,7 +73,6 @@ impl Scheduler {
|
||||
garbage_scopes: HashSet::new(),
|
||||
|
||||
current_priority: EventPriority::Low,
|
||||
waypoints: VecDeque::new(),
|
||||
|
||||
high_priorty: PriortySystem::new(),
|
||||
medium_priority: PriortySystem::new(),
|
||||
@@ -202,7 +199,9 @@ impl Scheduler {
|
||||
}
|
||||
|
||||
pub fn has_work(&self) -> bool {
|
||||
self.waypoints.len() > 0
|
||||
self.high_priorty.has_work()
|
||||
|| self.medium_priority.has_work()
|
||||
|| self.low_priority.has_work()
|
||||
}
|
||||
|
||||
pub fn has_pending_garbage(&self) -> bool {
|
||||
@@ -219,10 +218,10 @@ impl Scheduler {
|
||||
}
|
||||
|
||||
/// If a the fiber finishes its works (IE needs to be committed) the scheduler will drop the dirty scope
|
||||
pub fn work_with_deadline(
|
||||
&mut self,
|
||||
mut deadline: &mut Pin<Box<impl FusedFuture<Output = ()>>>,
|
||||
) -> FiberResult {
|
||||
pub async fn work_with_deadline<'a>(
|
||||
&'a mut self,
|
||||
deadline: &mut Pin<Box<impl FusedFuture<Output = ()>>>,
|
||||
) -> FiberResult<'a> {
|
||||
// check if we need to elevate priority
|
||||
self.current_priority = match (
|
||||
self.high_priorty.has_work(),
|
||||
@@ -234,11 +233,46 @@ impl Scheduler {
|
||||
(false, false, _) => EventPriority::Low,
|
||||
};
|
||||
|
||||
let mut is_ready = || -> bool { (&mut deadline).now_or_never().is_some() };
|
||||
let mut machine = DiffMachine::new_headless(&self.shared);
|
||||
|
||||
// TODO: remove this unwrap - proprogate errors out
|
||||
// self.get_current_fiber().work(is_ready).unwrap()
|
||||
todo!()
|
||||
let dirty_root = {
|
||||
let dirty_roots = match self.current_priority {
|
||||
EventPriority::High => &self.high_priorty.dirty_scopes,
|
||||
EventPriority::Medium => &self.medium_priority.dirty_scopes,
|
||||
EventPriority::Low => &self.low_priority.dirty_scopes,
|
||||
};
|
||||
let mut height = 0;
|
||||
let mut dirty_root = {
|
||||
let root = dirty_roots.iter().next();
|
||||
if root.is_none() {
|
||||
return FiberResult::Done(machine.mutations);
|
||||
}
|
||||
root.unwrap()
|
||||
};
|
||||
|
||||
for root in dirty_roots {
|
||||
if let Some(scope) = self.shared.get_scope(*root) {
|
||||
if scope.height < height {
|
||||
height = scope.height;
|
||||
dirty_root = root;
|
||||
}
|
||||
}
|
||||
}
|
||||
dirty_root
|
||||
};
|
||||
|
||||
match {
|
||||
let fut = machine.diff_scope(*dirty_root).fuse();
|
||||
pin_mut!(fut);
|
||||
|
||||
match futures_util::future::select(deadline, fut).await {
|
||||
futures_util::future::Either::Left((deadline, work_fut)) => true,
|
||||
futures_util::future::Either::Right((_, deadline_fut)) => false,
|
||||
}
|
||||
} {
|
||||
true => FiberResult::Done(machine.mutations),
|
||||
false => FiberResult::Interrupted,
|
||||
}
|
||||
}
|
||||
|
||||
// waits for a trigger, canceling early if the deadline is reached
|
||||
@@ -356,32 +390,6 @@ pub struct DirtyScope {
|
||||
start_tick: u32,
|
||||
}
|
||||
|
||||
/*
|
||||
A "waypoint" represents a frozen unit in time for the DiffingMachine to resume from. Whenever the deadline runs out
|
||||
while diffing, the diffing algorithm generates a Waypoint in order to easily resume from where it left off. Waypoints are
|
||||
fairly expensive to create, especially for big trees, so it's a good idea to pre-allocate them.
|
||||
|
||||
Waypoints are created pessimisticly, and are only generated when an "Error" state is bubbled out of the diffing machine.
|
||||
This saves us from wasting cycles book-keeping waypoints for 99% of edits where the deadline is not reached.
|
||||
*/
|
||||
pub struct Waypoint {
|
||||
// the progenitor of this waypoint
|
||||
root: ScopeId,
|
||||
|
||||
edits: Vec<DomEdit<'static>>,
|
||||
|
||||
// a saved position in the tree
|
||||
// these indicies continue to map through the tree into children nodes.
|
||||
// A sequence of usizes is all that is needed to represent the path to a node.
|
||||
tree_position: SmallVec<[usize; 10]>,
|
||||
|
||||
seen_scopes: HashSet<ScopeId>,
|
||||
|
||||
invalidate_scopes: HashSet<ScopeId>,
|
||||
|
||||
priority_level: EventPriority,
|
||||
}
|
||||
|
||||
pub struct PriortySystem {
|
||||
pub pending_scopes: Vec<ScopeId>,
|
||||
pub dirty_scopes: HashSet<ScopeId>,
|
||||
|
||||
@@ -298,11 +298,11 @@ impl VirtualDom {
|
||||
}
|
||||
|
||||
// Create work from the pending event queue
|
||||
self.scheduler.consume_pending_events();
|
||||
self.scheduler.consume_pending_events().unwrap();
|
||||
|
||||
// Work through the current subtree, and commit the results when it finishes
|
||||
// When the deadline expires, give back the work
|
||||
match self.scheduler.work_with_deadline(&mut deadline) {
|
||||
match self.scheduler.work_with_deadline(&mut deadline).await {
|
||||
FiberResult::Done(mut mutations) => {
|
||||
committed_mutations.extend(&mut mutations);
|
||||
|
||||
@@ -332,7 +332,10 @@ impl VirtualDom {
|
||||
true
|
||||
}
|
||||
|
||||
pub async fn wait_for_any_work(&self) {}
|
||||
pub async fn wait_for_any_work(&mut self) {
|
||||
let mut timeout = Box::pin(futures_util::future::pending().fuse());
|
||||
self.scheduler.wait_for_any_trigger(&mut timeout).await;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO!
|
||||
|
||||
Reference in new issue
Block a user