diff --git a/Cargo.lock b/Cargo.lock
index 9d49099..ec39ddf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 3
+[[package]]
+name = "bitflags"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
+
[[package]]
name = "bumpalo"
version = "3.15.4"
@@ -92,6 +98,7 @@ dependencies = [
name = "react-reconciler"
version = "0.1.0"
dependencies = [
+ "bitflags",
"console_error_panic_hook",
"react",
"shared",
@@ -109,6 +116,9 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "shared"
version = "0.1.0"
+dependencies = [
+ "web-sys",
+]
[[package]]
name = "syn"
diff --git a/examples/hello-world/src/main.tsx b/examples/hello-world/src/main.tsx
index e70c233..fa04a49 100644
--- a/examples/hello-world/src/main.tsx
+++ b/examples/hello-world/src/main.tsx
@@ -1,7 +1,6 @@
import {createRoot} from 'react-dom'
-
-const comp =
hello world
+const comp =
const root = createRoot(document.getElementById("root"))
root.render(comp)
diff --git a/packages/react-dom/src/lib.rs b/packages/react-dom/src/lib.rs
index 4487e37..a5c3771 100644
--- a/packages/react-dom/src/lib.rs
+++ b/packages/react-dom/src/lib.rs
@@ -1,3 +1,5 @@
+use std::rc::Rc;
+
use wasm_bindgen::prelude::*;
use react_reconciler::Reconciler;
@@ -13,7 +15,7 @@ mod host_config;
#[wasm_bindgen(js_name = createRoot)]
pub fn create_root(container: &JsValue) -> Renderer {
set_panic_hook();
- let reconciler = Reconciler::new(Box::new(ReactDomHostConfig));
+ let reconciler = Reconciler::new(Rc::new(ReactDomHostConfig));
let root = reconciler.create_container(container);
let renderer = Renderer::new(root, reconciler);
renderer
diff --git a/packages/react-reconciler/Cargo.toml b/packages/react-reconciler/Cargo.toml
index e30daae..183aaf8 100644
--- a/packages/react-reconciler/Cargo.toml
+++ b/packages/react-reconciler/Cargo.toml
@@ -20,6 +20,7 @@ shared = { path = "../shared" }
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
+bitflags = "2.5.0"
[dev-dependencies]
diff --git a/packages/react-reconciler/src/begin_work.rs b/packages/react-reconciler/src/begin_work.rs
new file mode 100644
index 0000000..5a3765a
--- /dev/null
+++ b/packages/react-reconciler/src/begin_work.rs
@@ -0,0 +1,68 @@
+use std::cell::RefCell;
+use std::rc::Rc;
+
+use wasm_bindgen::JsValue;
+
+use shared::{derive_from_js_value, log};
+
+use crate::child_fiber::{mount_child_fibers, reconcile_child_fibers};
+use crate::fiber::FiberNode;
+use crate::update_queue::process_update_queue;
+use crate::work_tags::WorkTag;
+
+pub fn begin_work(work_in_progress: Rc>) -> Option>> {
+ let tag = work_in_progress.clone().borrow().tag.clone();
+ return match tag {
+ WorkTag::FunctionComponent => None,
+ WorkTag::HostRoot => update_host_root(work_in_progress.clone()),
+ WorkTag::HostComponent => update_host_component(work_in_progress.clone()),
+ WorkTag::HostText => None
+ };
+}
+
+pub fn update_host_root(
+ work_in_progress: Rc>,
+) -> Option>> {
+ process_update_queue(work_in_progress.clone());
+ let next_children = work_in_progress.clone().borrow().memoized_state.clone();
+ log!("tag {:?}", next_children);
+ reconcile_children(work_in_progress.clone(), next_children);
+ work_in_progress.clone().borrow().child.clone()
+}
+
+
+pub fn update_host_component(
+ work_in_progress: Rc>,
+) -> Option>> {
+ let work_in_progress = Rc::clone(&work_in_progress);
+
+ let next_children = {
+ let ref_fiber_node = work_in_progress.borrow();
+ derive_from_js_value(ref_fiber_node.pending_props.clone().unwrap(), "children")
+ };
+
+ {
+ reconcile_children(work_in_progress.clone(), next_children);
+ }
+ work_in_progress.clone().borrow().child.clone()
+}
+
+pub fn reconcile_children(work_in_progress: Rc>, children: Option>) {
+ let work_in_progress = Rc::clone(&work_in_progress);
+ let current = { work_in_progress.borrow().alternate.clone() };
+ if current.is_some() {
+ // update
+ work_in_progress.borrow_mut().child = reconcile_child_fibers(
+ work_in_progress.clone(),
+ current.clone(),
+ children,
+ )
+ } else {
+ // mount
+ work_in_progress.borrow_mut().child = mount_child_fibers(
+ work_in_progress.clone(),
+ None,
+ children,
+ )
+ }
+}
\ No newline at end of file
diff --git a/packages/react-reconciler/src/child_fiber.rs b/packages/react-reconciler/src/child_fiber.rs
new file mode 100644
index 0000000..3469df1
--- /dev/null
+++ b/packages/react-reconciler/src/child_fiber.rs
@@ -0,0 +1,105 @@
+use std::cell::RefCell;
+use std::rc::Rc;
+
+use wasm_bindgen::JsValue;
+use web_sys::js_sys::{Object, Reflect};
+
+use shared::{derive_from_js_value, log, REACT_ELEMENT_TYPE};
+
+use crate::fiber::FiberNode;
+use crate::fiber_flags::Flags;
+use crate::work_tags::WorkTag;
+
+fn place_single_child(
+ fiber: Rc>,
+ should_track_effect: bool,
+) -> Rc> {
+ if should_track_effect {
+ let fiber = fiber.clone();
+ let mut fiber = fiber.borrow_mut();
+ fiber.flags |= Flags::Placement;
+ }
+ return fiber;
+}
+
+fn reconcile_single_element(
+ return_fiber: Rc>,
+ current_first_child: Option>>,
+ element: Option>,
+) -> Rc> {
+ let mut fiber = FiberNode::create_fiber_from_element(element.unwrap());
+ fiber._return = Some(return_fiber.clone());
+ Rc::new(RefCell::new(fiber))
+}
+
+fn reconcile_single_text_node(
+ return_fiber: Rc>,
+ current_first_child: Option>>,
+ content: Option>,
+) -> Rc> {
+ let props = Object::new();
+ Reflect::set(
+ &props,
+ &JsValue::from("content"),
+ &content.unwrap().clone(),
+ )
+ .expect("props panic");
+ let mut created = FiberNode::new(WorkTag::HostText, Some(Rc::new(Object::into(props))), None);
+ created._return = Some(return_fiber.clone());
+ Rc::new(RefCell::new(created))
+}
+
+fn _reconcile_child_fibers(
+ return_fiber: Rc>,
+ current_first_child: Option>>,
+ new_child: Option>,
+ should_track_effect: bool,
+) -> Option>> {
+ if new_child.is_some() {
+ let new_child = Rc::clone(&new_child.unwrap());
+
+ if new_child.is_string() {
+ return Some(place_single_child(
+ reconcile_single_text_node(
+ return_fiber,
+ current_first_child,
+ Some(new_child.clone()),
+ ),
+ should_track_effect,
+ ));
+ } else if new_child.is_object() {
+ log!("{:?}", new_child);
+ let _typeof = Rc::clone(&derive_from_js_value(new_child.clone(), "$$typeof").unwrap())
+ .as_string()
+ .unwrap();
+ if _typeof == REACT_ELEMENT_TYPE {
+ return Some(place_single_child(
+ reconcile_single_element(
+ return_fiber,
+ current_first_child,
+ Some(new_child.clone()),
+ ),
+ should_track_effect,
+ ));
+ }
+ }
+ }
+ log!("Unsupported child type when reconcile");
+ return None;
+}
+
+pub fn reconcile_child_fibers(
+ return_fiber: Rc>,
+ current_first_child: Option>>,
+ new_child: Option>,
+) -> Option>> {
+ _reconcile_child_fibers(return_fiber, current_first_child, new_child, true)
+}
+
+pub fn mount_child_fibers(
+ return_fiber: Rc>,
+ current_first_child: Option>>,
+ new_child: Option>,
+) -> Option>> {
+ _reconcile_child_fibers(return_fiber, current_first_child, new_child, false)
+}
\ No newline at end of file
diff --git a/packages/react-reconciler/src/fiber.rs b/packages/react-reconciler/src/fiber.rs
index 96c2bc7..26b013c 100644
--- a/packages/react-reconciler/src/fiber.rs
+++ b/packages/react-reconciler/src/fiber.rs
@@ -1,2 +1,235 @@
+use std::any::Any;
+use std::cell::RefCell;
+use std::collections::VecDeque;
+use std::fmt::{Debug, Formatter};
+use std::ops::Deref;
+use std::rc::Rc;
+
+use wasm_bindgen::JsValue;
+use web_sys::js_sys::Reflect;
+
+use shared::derive_from_js_value;
+
+use crate::fiber_flags::Flags;
+use crate::update_queue::{Update, UpdateQueue, UpdateType};
+use crate::work_tags::WorkTag;
+
#[derive(Debug)]
-pub struct FiberRootNode {}
\ No newline at end of file
+pub enum StateNode {
+ FiberRootNode(Rc>),
+ Element(Rc),
+}
+
+#[derive(Debug)]
+pub struct FiberNode {
+ pub tag: WorkTag,
+ pub pending_props: Option>,
+ key: Option,
+ pub state_node: Option>,
+ pub update_queue: Option>>,
+ pub _return: Option>>,
+ pub sibling: Option>>,
+ pub child: Option>>,
+ pub alternate: Option>>,
+ pub _type: Option>,
+ pub flags: Flags,
+ pub subtree_flags: Flags,
+ pub memoized_props: Option>,
+ pub memoized_state: Option>,
+}
+
+impl FiberNode {
+ pub fn new(tag: WorkTag, pending_props: Option>, key: Option) -> Self {
+ Self {
+ tag,
+ pending_props,
+ key,
+ state_node: None,
+ update_queue: None,
+ _return: None,
+ sibling: None,
+ child: None,
+ alternate: None,
+ _type: None,
+ memoized_props: None,
+ memoized_state: None,
+ flags: Flags::NoFlags,
+ subtree_flags: Flags::NoFlags,
+ }
+ }
+
+ pub fn create_fiber_from_element(ele: Rc) -> Self {
+ let _type = derive_from_js_value(ele.clone(), "type");
+ let key = match derive_from_js_value(ele.clone(), "key") {
+ None => None,
+ Some(k) => k.as_string(),
+ };
+ let props = derive_from_js_value(ele.clone(), "props");
+
+ let mut fiber_tag = WorkTag::FunctionComponent;
+ if _type.is_some() && (*_type.as_ref().unwrap()).is_string() {
+ fiber_tag = WorkTag::HostComponent
+ }
+ let mut fiber = FiberNode::new(fiber_tag, props, key);
+ fiber._type = _type;
+ fiber
+ }
+
+ pub fn enqueue_update(&mut self, update: Update) {
+ let mut update_queue = match &self.update_queue {
+ None => {
+ return;
+ }
+ Some(a) => a.clone(),
+ };
+
+ let mut u = update_queue.borrow_mut();
+ u.shared.pending = Some(update);
+ }
+
+ pub fn initialize_update_queue(&mut self) {
+ self.update_queue = Some(Rc::new(RefCell::new(UpdateQueue {
+ shared: UpdateType {
+ pending: Some(Update { action: None }),
+ },
+ })));
+ }
+
+ pub fn create_work_in_progress(
+ current: Rc>,
+ pending_props: Rc,
+ ) -> Rc> {
+ let c_rc = Rc::clone(¤t);
+ let w = {
+ let c = c_rc.borrow();
+ c.deref().alternate.clone()
+ };
+
+ return if w.is_none() {
+ let mut wip = {
+ let c = c_rc.borrow();
+ let mut wip = FiberNode::new(c.tag.clone(), c.pending_props.clone(), c.key.clone());
+ wip.update_queue = Some(c.update_queue.as_ref().unwrap().clone());
+ wip.flags = c.flags.clone();
+ wip.child = c.child.clone();
+ wip.memoized_props = c.memoized_props.clone();
+ wip.memoized_state = c.memoized_state.clone();
+ wip
+ };
+ wip._type = c_rc.borrow()._type.clone();
+ wip.state_node = c_rc.borrow().state_node.clone();
+ wip.alternate = Some(current);
+ let wip_rc = Rc::new(RefCell::new(wip));
+ let mut fibler_node = c_rc.borrow_mut();
+ fibler_node.alternate = Some(wip_rc.clone());
+ wip_rc
+ } else {
+ let c = c_rc.borrow();
+ let a = w.clone().unwrap();
+ let mut wip = a.borrow_mut();
+
+ wip.pending_props = Some(pending_props.clone());
+ wip.update_queue = Some(c.update_queue.as_ref().unwrap().clone());
+ wip.flags = c.flags.clone();
+ wip.child = Some(Rc::clone(c.child.as_ref().unwrap()));
+ wip.memoized_props = c.memoized_props.clone();
+ wip.memoized_state = c.memoized_state.clone();
+ w.clone().unwrap()
+ };
+ }
+
+ pub fn derive_state_node(fiber: Rc>) -> Option> {
+ let state_node = fiber.clone().borrow().state_node.clone();
+ if state_node.is_none() {
+ return None;
+ }
+
+ Some(match &*state_node.unwrap().clone() {
+ StateNode::FiberRootNode(root) => root.clone().borrow().container.clone(),
+ StateNode::Element(ele) => ele.clone(),
+ })
+ }
+}
+
+pub struct FiberRootNode {
+ pub container: Rc,
+ pub current: Rc>,
+ pub finished_work: Option>>,
+}
+
+impl FiberRootNode {
+ pub fn new(container: Rc, host_root_fiber: Rc>) -> Self {
+ Self {
+ container,
+ current: host_root_fiber,
+ finished_work: None,
+ }
+ }
+}
+
+impl Debug for FiberRootNode {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ let mut root = self.current.clone().borrow().alternate.clone();
+ Ok(if let Some(node) = root {
+ let mut queue = VecDeque::new();
+ queue.push_back(Rc::clone(&node));
+
+ while let Some(current) = queue.pop_front() {
+ let current_ref = current.borrow();
+
+ match current_ref.tag {
+ WorkTag::FunctionComponent => {
+ write!(f, "{:?}", current.borrow()._type.as_ref().unwrap());
+ }
+ WorkTag::HostRoot => {
+ write!(f, "{:?}", WorkTag::HostRoot);
+ }
+ WorkTag::HostComponent => {
+ write!(f, "{:?}", current.borrow()._type.as_ref().unwrap().as_string().unwrap());
+ }
+ WorkTag::HostText => {
+ write!(
+ f,
+ "{:?}",
+ Reflect::get(
+ current.borrow().pending_props.as_ref().unwrap(),
+ &JsValue::from_str("content"),
+ )
+ .unwrap()
+ .as_string()
+ .unwrap(),
+ );
+ }
+ };
+ if let Some(ref child) = current_ref.child {
+ queue.push_back(Rc::clone(child));
+ let mut sibling = child.clone().borrow().sibling.clone();
+ while sibling.is_some() {
+ queue.push_back(Rc::clone(sibling.as_ref().unwrap()));
+ sibling = sibling.as_ref().unwrap().clone().borrow().sibling.clone();
+ }
+ }
+
+ if let Some(next) = queue.front() {
+ let next_ref = next.borrow();
+ if let (Some(current_parent), Some(next_parent)) =
+ (current_ref._return.as_ref(), next_ref._return.as_ref())
+ {
+ if !Rc::ptr_eq(current_parent, next_parent) {
+ writeln!(f, "");
+ writeln!(f, "------------------------------------");
+ continue;
+ }
+ }
+
+ if current_ref._return.is_some() {
+ write!(f, ",");
+ } else {
+ writeln!(f, "");
+ writeln!(f, "------------------------------------");
+ }
+ }
+ }
+ })
+ }
+}
diff --git a/packages/react-reconciler/src/fiber_flags.rs b/packages/react-reconciler/src/fiber_flags.rs
new file mode 100644
index 0000000..8c7ced2
--- /dev/null
+++ b/packages/react-reconciler/src/fiber_flags.rs
@@ -0,0 +1,15 @@
+use bitflags::bitflags;
+
+bitflags! {
+ #[derive(Debug, Clone)]
+ pub struct Flags: u8 {
+ const NoFlags = 0b00000000;
+ const Placement = 0b00000010;
+ const Update = 0b00000100;
+ const ChildDeletion = 0b00010000;
+ }
+}
+
+pub fn get_mutation_mask() -> Flags {
+ Flags::Placement | Flags::Update | Flags::ChildDeletion
+}
\ No newline at end of file
diff --git a/packages/react-reconciler/src/lib.rs b/packages/react-reconciler/src/lib.rs
index 31ddbf6..990e484 100644
--- a/packages/react-reconciler/src/lib.rs
+++ b/packages/react-reconciler/src/lib.rs
@@ -3,12 +3,19 @@ use std::cell::RefCell;
use std::rc::Rc;
use wasm_bindgen::JsValue;
-use web_sys::{Element, window};
-use web_sys::js_sys::Reflect;
-use crate::fiber::FiberRootNode;
+use crate::fiber::{FiberNode, FiberRootNode, StateNode};
+use crate::update_queue::{create_update, enqueue_update};
+use crate::work_loop::WorkLoop;
+use crate::work_tags::WorkTag;
pub mod fiber;
+mod fiber_flags;
+mod work_tags;
+mod update_queue;
+mod work_loop;
+mod begin_work;
+mod child_fiber;
pub trait HostConfig {
fn create_text_instance(&self, content: String) -> Rc;
@@ -18,28 +25,28 @@ pub trait HostConfig {
}
pub struct Reconciler {
- host_config: Box,
+ host_config: Rc,
}
impl Reconciler {
- pub fn new(host_config: Box) -> Self {
+ pub fn new(host_config: Rc) -> Self {
Reconciler { host_config }
}
pub fn create_container(&self, container: &JsValue) -> Rc> {
- Rc::new(RefCell::new(FiberRootNode {}))
+ let host_root_fiber = Rc::new(RefCell::new(FiberNode::new(WorkTag::HostRoot, None, None)));
+ host_root_fiber.clone().borrow_mut().initialize_update_queue();
+ let root = Rc::new(RefCell::new(FiberRootNode::new(Rc::new(container.clone()), host_root_fiber.clone())));
+ let r1 = root.clone();
+ host_root_fiber.borrow_mut().state_node = Some(Rc::new(StateNode::FiberRootNode(r1)));
+ root.clone()
}
pub fn update_container(&self, element: Rc, root: Rc>) {
- let props = Reflect::get(&*element, &JsValue::from_str("props")).unwrap();
- let _type = Reflect::get(&*element, &JsValue::from_str("type")).unwrap();
- let children = Reflect::get(&props, &JsValue::from_str("children")).unwrap();
- let text_instance = self.host_config.create_text_instance(children.as_string().unwrap());
- let div_instance = self.host_config.create_instance(_type.as_string().unwrap());
- self.host_config.append_initial_child(div_instance.clone(), text_instance);
- let window = window().unwrap();
- let document = window.document().unwrap();
- let body = document.body().expect("document should have a body");
- body.append_child(&*div_instance.clone().downcast::().unwrap());
+ let host_root_fiber = Rc::clone(&root).borrow().current.clone();
+ let update = create_update(element);
+ enqueue_update(host_root_fiber.borrow(), update);
+ let mut work_loop = WorkLoop::new(self.host_config.clone());
+ work_loop.schedule_update_on_fiber(host_root_fiber);
}
}
diff --git a/packages/react-reconciler/src/update_queue.rs b/packages/react-reconciler/src/update_queue.rs
new file mode 100644
index 0000000..39694cc
--- /dev/null
+++ b/packages/react-reconciler/src/update_queue.rs
@@ -0,0 +1,73 @@
+use std::cell::{Ref, RefCell};
+use std::rc::Rc;
+
+use wasm_bindgen::{JsCast, JsValue};
+use web_sys::js_sys::Function;
+
+use shared::log;
+
+use crate::fiber::FiberNode;
+
+#[derive(Clone, Debug)]
+pub struct UpdateAction;
+
+
+#[derive(Clone, Debug)]
+pub struct Update {
+ pub action: Option>,
+}
+
+#[derive(Clone, Debug)]
+pub struct UpdateType {
+ pub pending: Option,
+}
+
+
+#[derive(Clone, Debug)]
+pub struct UpdateQueue {
+ pub shared: UpdateType,
+}
+
+
+pub fn create_update(action: Rc) -> Update {
+ Update { action: Some(action) }
+}
+
+pub fn enqueue_update(fiber: Ref, update: Update) {
+ if fiber.update_queue.is_some() {
+ let uq = fiber.update_queue.clone().unwrap();
+ let mut update_queue = uq.borrow_mut();
+ update_queue.shared.pending = Some(update);
+ }
+}
+
+pub fn process_update_queue(fiber: Rc>) {
+ let mut rc_fiber = fiber.clone();
+ let mut fiber = rc_fiber.borrow_mut();
+ let mut new_state = None;
+ match fiber.update_queue.clone() {
+ None => {
+ log!("{:?} process_update_queue, update_queue is empty", fiber)
+ }
+ Some(q) => {
+ let update_queue = q.clone();
+ let pending = update_queue.clone().borrow().shared.pending.clone();
+ update_queue.borrow_mut().shared.pending = None;
+ if pending.is_some() {
+ let action = pending.unwrap().action;
+ match action {
+ None => {}
+ Some(action) => {
+ let f = action.dyn_ref::();
+ new_state = match f {
+ None => Some(action.clone()),
+ Some(f) => Some(Rc::new(f.call0(&JsValue::null()).unwrap())),
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fiber.memoized_state = new_state
+}
\ No newline at end of file
diff --git a/packages/react-reconciler/src/work_loop.rs b/packages/react-reconciler/src/work_loop.rs
new file mode 100644
index 0000000..a166880
--- /dev/null
+++ b/packages/react-reconciler/src/work_loop.rs
@@ -0,0 +1,128 @@
+use std::cell::RefCell;
+use std::rc::Rc;
+
+use wasm_bindgen::JsValue;
+
+use shared::log;
+
+use crate::begin_work::begin_work;
+use crate::fiber::{FiberNode, FiberRootNode, StateNode};
+use crate::HostConfig;
+use crate::work_tags::WorkTag;
+
+pub struct WorkLoop {
+ work_in_progress: Option>>,
+}
+
+impl WorkLoop {
+ pub fn new(host_config: Rc) -> Self {
+ Self {
+ work_in_progress: None,
+ }
+ }
+
+ pub fn schedule_update_on_fiber(&mut self, fiber: Rc>) {
+ let root = self.mark_update_lane_from_fiber_to_root(fiber);
+ if root.is_none() {
+ return;
+ }
+ log!(
+ "schedule_update_on_fiber - root container: {:?}",
+ root.clone().unwrap().clone().borrow().container
+ );
+
+ self.ensure_root_is_scheduled(root.unwrap())
+ }
+
+ pub fn mark_update_lane_from_fiber_to_root(
+ &self,
+ fiber: Rc>,
+ ) -> Option>> {
+ let mut node = Rc::clone(&fiber);
+ let mut parent = Rc::clone(&fiber).borrow()._return.clone();
+
+ while parent.is_some() {
+ node = parent.clone().unwrap();
+ let rc = Rc::clone(&parent.unwrap());
+ let rc_ref = rc.borrow();
+ let next = match rc_ref._return.as_ref() {
+ None => None,
+ Some(node) => {
+ let a = node.clone();
+ Some(a)
+ }
+ };
+ parent = next;
+ }
+
+ let fiber_node_rc = Rc::clone(&node);
+ let fiber_node = fiber_node_rc.borrow();
+ if fiber_node.tag == WorkTag::HostRoot {
+ match fiber_node.state_node.clone() {
+ None => {}
+ Some(state_node) => {
+ return match &*state_node {
+ StateNode::FiberRootNode(fiber_root_node) => {
+ Some(Rc::clone(&fiber_root_node))
+ }
+ StateNode::Element(_) => todo!(),
+ };
+ }
+ }
+
+ // let Some(StateNode::FiberRootNode(fiber_root_node)) = fiber_node.state_node.clone();
+ // return Some(Rc::clone(&fiber_root_node));
+ }
+
+ None
+ }
+
+ fn ensure_root_is_scheduled(&mut self, root: Rc>) {
+ self.perform_sync_work_on_root(root);
+ }
+
+ fn perform_sync_work_on_root(&mut self, root: Rc>) {
+ self.prepare_fresh_stack(Rc::clone(&root));
+
+ loop {
+ self.work_loop();
+ break;
+ }
+
+ log!("{:?}", *root.clone().borrow());
+ // commit
+ }
+
+ fn prepare_fresh_stack(&mut self, root: Rc>) {
+ let root = Rc::clone(&root);
+ self.work_in_progress = Some(FiberNode::create_work_in_progress(
+ root.borrow().current.clone(),
+ Rc::new(JsValue::null()),
+ ));
+ }
+
+ fn work_loop(&mut self) {
+ while self.work_in_progress.is_some() {
+ log!(
+ "work_loop - work_in_progress {:?}",
+ self.work_in_progress.clone().unwrap().clone().borrow().tag
+ );
+ self.perform_unit_of_work(self.work_in_progress.clone().unwrap());
+ }
+ }
+
+ fn perform_unit_of_work(&mut self, fiber: Rc>) {
+ let next = begin_work(fiber.clone());
+
+ if next.is_none() {
+ // self.complete_unit_of_work(fiber.clone())
+ self.work_in_progress = None;
+ } else {
+ log!(
+ "perform_unit_of_work - next {:?}",
+ next.clone().unwrap().clone().borrow().tag
+ );
+ self.work_in_progress = Some(next.unwrap());
+ }
+ }
+}
diff --git a/packages/react-reconciler/src/work_tags.rs b/packages/react-reconciler/src/work_tags.rs
new file mode 100644
index 0000000..187a6ce
--- /dev/null
+++ b/packages/react-reconciler/src/work_tags.rs
@@ -0,0 +1,7 @@
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum WorkTag {
+ FunctionComponent = 0,
+ HostRoot = 3,
+ HostComponent = 5,
+ HostText = 6,
+}
\ No newline at end of file
diff --git a/packages/react/src/lib.rs b/packages/react/src/lib.rs
index 03d41f8..5bdaaab 100644
--- a/packages/react/src/lib.rs
+++ b/packages/react/src/lib.rs
@@ -8,11 +8,11 @@ pub fn jsx_dev(_type: &JsValue, config: &JsValue, key: &JsValue) -> JsValue {
let react_element = Object::new();
Reflect::set(
&react_element,
- &"&&typeof".into(),
+ &"$$typeof".into(),
&JsValue::from_str(REACT_ELEMENT_TYPE),
)
.expect("$$typeof panic");
- Reflect::set(&react_element, &"type".into(), _type).expect("_type panic");
+ Reflect::set(&react_element, &"type".into(), _type).expect("type panic");
Reflect::set(&react_element, &"key".into(), key).expect("key panic");
let conf = config.dyn_ref::