|
@@ -1,20 +1,14 @@
|
|
-use std::cell::RefCell;
|
|
|
|
|
|
+use std::cell::{Ref, RefCell};
|
|
|
|
|
|
-use crate::{
|
|
|
|
- innerlude::{DirtyScope, Scheduler, SchedulerMsg},
|
|
|
|
- scope_context::ScopeContext,
|
|
|
|
- scopes::{ScopeId, ScopeState},
|
|
|
|
-};
|
|
|
|
-use rustc_hash::FxHashSet;
|
|
|
|
-use slab::Slab;
|
|
|
|
-use std::{collections::BTreeSet, rc::Rc};
|
|
|
|
|
|
+use crate::{innerlude::Scheduler, scope_context::ScopeContext, scopes::ScopeId};
|
|
|
|
+use std::rc::Rc;
|
|
|
|
|
|
thread_local! {
|
|
thread_local! {
|
|
- static RUNTIMES: RefCell<Vec<Runtime>> = RefCell::new(vec![]);
|
|
|
|
|
|
+ static RUNTIMES: RefCell<Vec<Rc<Runtime>>> = RefCell::new(vec![]);
|
|
}
|
|
}
|
|
|
|
|
|
/// Pushes a new scope onto the stack
|
|
/// Pushes a new scope onto the stack
|
|
-pub(crate) fn push_runtime(runtime: Runtime) {
|
|
|
|
|
|
+pub(crate) fn push_runtime(runtime: Rc<Runtime>) {
|
|
RUNTIMES.with(|stack| stack.borrow_mut().push(runtime));
|
|
RUNTIMES.with(|stack| stack.borrow_mut().push(runtime));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -30,7 +24,7 @@ where
|
|
{
|
|
{
|
|
RUNTIMES.with(|stack| {
|
|
RUNTIMES.with(|stack| {
|
|
let stack = stack.borrow();
|
|
let stack = stack.borrow();
|
|
- stack.last().map(f)
|
|
|
|
|
|
+ stack.last().map(|r| f(&**r))
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
@@ -42,28 +36,50 @@ where
|
|
with_runtime(|runtime| {
|
|
with_runtime(|runtime| {
|
|
runtime
|
|
runtime
|
|
.current_scope_id()
|
|
.current_scope_id()
|
|
- .and_then(|scope| runtime.get_context(scope).map(f))
|
|
|
|
|
|
+ .and_then(|scope| runtime.get_context(scope).map(|sc| f(&*sc)))
|
|
})
|
|
})
|
|
.flatten()
|
|
.flatten()
|
|
}
|
|
}
|
|
|
|
|
|
pub struct Runtime {
|
|
pub struct Runtime {
|
|
- pub(crate) scope_contexts: Slab<ScopeContext>,
|
|
|
|
|
|
+ pub(crate) scope_contexts: RefCell<Vec<Option<ScopeContext>>>,
|
|
pub(crate) scheduler: Rc<Scheduler>,
|
|
pub(crate) scheduler: Rc<Scheduler>,
|
|
|
|
|
|
// While diffing we need some sort of way of breaking off a stream of suspended mutations.
|
|
// While diffing we need some sort of way of breaking off a stream of suspended mutations.
|
|
pub(crate) scope_stack: RefCell<Vec<ScopeId>>,
|
|
pub(crate) scope_stack: RefCell<Vec<ScopeId>>,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+impl Drop for Runtime {
|
|
|
|
+ fn drop(&mut self) {
|
|
|
|
+ // todo: do this better
|
|
|
|
+ pop_runtime();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
impl Runtime {
|
|
impl Runtime {
|
|
pub(crate) fn new(scheduler: Rc<Scheduler>) -> Rc<Self> {
|
|
pub(crate) fn new(scheduler: Rc<Scheduler>) -> Rc<Self> {
|
|
- Rc::new(Self {
|
|
|
|
|
|
+ let runtime = Rc::new(Self {
|
|
scheduler,
|
|
scheduler,
|
|
|
|
|
|
scope_contexts: Default::default(),
|
|
scope_contexts: Default::default(),
|
|
|
|
|
|
scope_stack: Default::default(),
|
|
scope_stack: Default::default(),
|
|
- })
|
|
|
|
|
|
+ });
|
|
|
|
+ push_runtime(runtime.clone());
|
|
|
|
+ runtime
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Create a scope context. This slab is synchronized with the scope slab.
|
|
|
|
+ pub(crate) fn create_context_at(&self, id: ScopeId, context: ScopeContext) {
|
|
|
|
+ let mut contexts = self.scope_contexts.borrow_mut();
|
|
|
|
+ if contexts.len() <= id.0 {
|
|
|
|
+ contexts.resize_with(id.0 + 1, Default::default);
|
|
|
|
+ }
|
|
|
|
+ contexts[id.0] = Some(context);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub(crate) fn remove_context(&self, id: ScopeId) {
|
|
|
|
+ self.scope_contexts.borrow_mut()[id.0] = None;
|
|
}
|
|
}
|
|
|
|
|
|
/// Get the current scope id
|
|
/// Get the current scope id
|
|
@@ -71,17 +87,13 @@ impl Runtime {
|
|
self.scope_stack.borrow().last().copied()
|
|
self.scope_stack.borrow().last().copied()
|
|
}
|
|
}
|
|
|
|
|
|
- /// Get the state for any scope given its ID
|
|
|
|
|
|
+ /// Get the context for any scope given its ID
|
|
///
|
|
///
|
|
/// This is useful for inserting or removing contexts from a scope, or rendering out its root node
|
|
/// This is useful for inserting or removing contexts from a scope, or rendering out its root node
|
|
- pub fn get_context(&self, id: ScopeId) -> Option<&ScopeContext> {
|
|
|
|
- self.scope_contexts.get(id.0).map(|f| &*f)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// Get the single scope at the top of the Runtime tree that will always be around
|
|
|
|
- ///
|
|
|
|
- /// This scope has a ScopeId of 0 and is the root of the tree
|
|
|
|
- pub fn base_context(&self) -> &ScopeContext {
|
|
|
|
- self.get_context(ScopeId(0)).unwrap()
|
|
|
|
|
|
+ pub fn get_context(&self, id: ScopeId) -> Option<Ref<'_, ScopeContext>> {
|
|
|
|
+ Ref::filter_map(self.scope_contexts.borrow(), |contexts| {
|
|
|
|
+ contexts.get(id.0).and_then(|f| f.as_ref())
|
|
|
|
+ })
|
|
|
|
+ .ok()
|
|
}
|
|
}
|
|
}
|
|
}
|