Assume the virtual dom is not rendering while not diffing components (#3406)
* Invert when the rendering flag is set * Add a playwright test to make sure effects, and web-sys integration is working * fix playwright test
This commit is contained in:
1 parent
cf1940cdac
commit
01ebccc269
8 files changed
+79
-15
No files matched your search
@@ -1,5 +1,4 @@
|
||||
use crate::innerlude::ScopeOrder;
|
||||
use crate::Runtime;
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
@@ -29,13 +28,11 @@ impl Effect {
|
||||
self.effect.borrow_mut().push_back(Box::new(f));
|
||||
}
|
||||
|
||||
pub(crate) fn run(&self, runtime: &Runtime) {
|
||||
runtime.rendering.set(false);
|
||||
pub(crate) fn run(&self) {
|
||||
let mut effect = self.effect.borrow_mut();
|
||||
while let Some(f) = effect.pop_front() {
|
||||
f();
|
||||
}
|
||||
runtime.rendering.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ impl Runtime {
|
||||
|
||||
Rc::new(Self {
|
||||
sender,
|
||||
rendering: Cell::new(true),
|
||||
rendering: Cell::new(false),
|
||||
scope_states: Default::default(),
|
||||
scope_stack: Default::default(),
|
||||
suspense_stack: Default::default(),
|
||||
@@ -108,6 +108,14 @@ impl Runtime {
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a closure with the rendering flag set to true
|
||||
pub(crate) fn while_rendering<T>(&self, f: impl FnOnce() -> T) -> T {
|
||||
self.rendering.set(true);
|
||||
let result = f();
|
||||
self.rendering.set(false);
|
||||
result
|
||||
}
|
||||
|
||||
/// Create a scope context. This slab is synchronized with the scope slab.
|
||||
pub(crate) fn create_scope(&self, context: Scope) {
|
||||
let id = context.id;
|
||||
@@ -380,9 +388,7 @@ impl Runtime {
|
||||
);
|
||||
for listener in listeners.into_iter().rev() {
|
||||
if let AttributeValue::Listener(listener) = listener {
|
||||
self.rendering.set(false);
|
||||
listener.call(uievent.clone());
|
||||
self.rendering.set(true);
|
||||
let metadata = uievent.metadata.borrow();
|
||||
|
||||
if !metadata.propagates {
|
||||
@@ -420,9 +426,7 @@ impl Runtime {
|
||||
// Only call the listener if this is the exact target element.
|
||||
if attr.name.get(2..) == Some(name) && target_path == this_path {
|
||||
if let AttributeValue::Listener(listener) = &attr.value {
|
||||
self.rendering.set(false);
|
||||
listener.call(uievent.clone());
|
||||
self.rendering.set(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +275,6 @@ impl Runtime {
|
||||
|
||||
// poll the future with the scope on the stack
|
||||
let poll_result = self.with_scope_on_stack(task.scope, || {
|
||||
self.rendering.set(false);
|
||||
self.current_task.set(Some(id));
|
||||
|
||||
let poll_result = task.task.borrow_mut().as_mut().poll(&mut cx);
|
||||
@@ -293,7 +292,6 @@ impl Runtime {
|
||||
|
||||
poll_result
|
||||
});
|
||||
self.rendering.set(true);
|
||||
self.current_task.set(None);
|
||||
|
||||
poll_result
|
||||
|
||||
@@ -511,7 +511,7 @@ impl VirtualDom {
|
||||
|
||||
// At this point, we have finished running all tasks that are pending and we haven't found any scopes to rerun. This means it is safe to run our lowest priority work: effects
|
||||
while let Some(effect) = self.pop_effect() {
|
||||
effect.run(&self.runtime);
|
||||
effect.run();
|
||||
// Check if any new scopes are queued for rerun
|
||||
self.queue_events();
|
||||
if self.has_dirty_scopes() {
|
||||
@@ -562,7 +562,10 @@ impl VirtualDom {
|
||||
#[instrument(skip(self, to), level = "trace", name = "VirtualDom::rebuild")]
|
||||
pub fn rebuild(&mut self, to: &mut impl WriteMutations) {
|
||||
let _runtime = RuntimeGuard::new(self.runtime.clone());
|
||||
let new_nodes = self.run_scope(ScopeId::ROOT);
|
||||
let new_nodes = self
|
||||
.runtime
|
||||
.clone()
|
||||
.while_rendering(|| self.run_scope(ScopeId::ROOT));
|
||||
|
||||
self.scopes[ScopeId::ROOT.0].last_rendered_node = Some(new_nodes.clone());
|
||||
|
||||
@@ -593,7 +596,9 @@ impl VirtualDom {
|
||||
}
|
||||
Work::RerunScope(scope) => {
|
||||
// If the scope is dirty, run the scope and get the mutations
|
||||
self.run_and_diff_scope(Some(to), scope.id);
|
||||
self.runtime.clone().while_rendering(|| {
|
||||
self.run_and_diff_scope(Some(to), scope.id);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -700,7 +705,9 @@ impl VirtualDom {
|
||||
.is_some();
|
||||
if run_scope {
|
||||
// If the scope is dirty, run the scope and get the mutations
|
||||
self.run_and_diff_scope(None::<&mut NoOpMutations>, scope_id);
|
||||
self.runtime.clone().while_rendering(|| {
|
||||
self.run_and_diff_scope(None::<&mut NoOpMutations>, scope_id);
|
||||
});
|
||||
|
||||
tracing::trace!("Ran scope {:?} during suspense", scope_id);
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user