Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blog-6 #2

Open
wants to merge 3 commits into
base: blog-5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/react-dom/src/host_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ impl HostConfig for ReactDomHostConfig {
let c = child.clone().downcast::<Node>().unwrap();
match p.append_child(&c) {
Ok(_) => {
log!("append_initial_child successfully jsvalue {:?} {:?}", p, child);
log!("append_initial_child successfully {:?} {:?}", p, c);
}
Err(_) => todo!(),
}
}

fn append_child_to_container(&self, child: Rc<dyn Any>, parent: Rc<dyn Any>) {
todo!()
self.append_initial_child(parent, child)
}
}
15 changes: 11 additions & 4 deletions packages/react-dom/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
use std::rc::Rc;

use wasm_bindgen::prelude::*;
use web_sys::Node;

use react_reconciler::Reconciler;

use crate::host_config::ReactDomHostConfig;
use crate::renderer::Renderer;
use crate::utils::set_panic_hook;

mod utils;
mod renderer;
mod host_config;
mod renderer;
mod utils;

#[wasm_bindgen(js_name = createRoot)]
pub fn create_root(container: &JsValue) -> Renderer {
set_panic_hook();
let reconciler = Reconciler::new(Rc::new(ReactDomHostConfig));
let root = reconciler.create_container(container);
let node = match container.clone().dyn_into::<Node>() {
Ok(node) => node,
Err(_) => {
panic!("container should be Node")
}
};
let root = reconciler.create_container(Rc::new(node));
let renderer = Renderer::new(root, reconciler);
renderer
}
}
5 changes: 3 additions & 2 deletions packages/react-dom/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl Renderer {
#[wasm_bindgen]
impl Renderer {
pub fn render(&self, element: &JsValue) {
self.reconciler.update_container(Rc::new(element.clone()), self.root.clone())
self.reconciler
.update_container(Rc::new(element.clone()), self.root.clone())
}
}
}
3 changes: 1 addition & 2 deletions packages/react-reconciler/src/begin_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::rc::Rc;

use wasm_bindgen::JsValue;

use shared::{derive_from_js_value, log};
use shared::derive_from_js_value;

use crate::child_fiber::{mount_child_fibers, reconcile_child_fibers};
use crate::fiber::FiberNode;
Expand All @@ -25,7 +25,6 @@ pub fn update_host_root(
) -> Option<Rc<RefCell<FiberNode>>> {
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()
}
Expand Down
30 changes: 15 additions & 15 deletions packages/react-reconciler/src/child_fiber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ 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 shared::{derive_from_js_value, REACT_ELEMENT_TYPE};

use crate::fiber::FiberNode;
use crate::fiber_flags::Flags;
Expand Down Expand Up @@ -64,23 +64,23 @@ fn _reconcile_child_fibers(
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,
));
if let Some(_typeof) =
Rc::clone(&derive_from_js_value(new_child.clone(), "$$typeof").unwrap()).as_string()
{
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");
todo!("Unsupported child type when reconcile");
return None;
}

Expand Down
136 changes: 136 additions & 0 deletions packages/react-reconciler/src/commit_work.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use std::any::Any;
use std::cell::RefCell;
use std::rc::Rc;

use crate::fiber::{FiberNode, StateNode};
use crate::fiber_flags::{Flags, get_mutation_mask};
use crate::HostConfig;
use crate::work_tags::WorkTag;

pub struct CommitWork {
next_effect: Option<Rc<RefCell<FiberNode>>>,
host_config: Rc<dyn HostConfig>,
}

impl CommitWork {
pub fn new(host_config: Rc<dyn HostConfig>) -> Self {
Self {
next_effect: None,
host_config,
}
}
pub fn commit_mutation_effects(&mut self, finished_work: Rc<RefCell<FiberNode>>) {
self.next_effect = Some(finished_work);
while self.next_effect.is_some() {
let next_effect = self.next_effect.clone().unwrap().clone();
let child = next_effect.borrow().child.clone();
if child.is_some()
&& get_mutation_mask().contains(next_effect.borrow().subtree_flags.clone())
{
self.next_effect = child;
} else {
while self.next_effect.is_some() {
self.commit_mutation_effects_on_fiber(self.next_effect.clone().unwrap());
let sibling = self
.next_effect
.clone()
.clone()
.unwrap()
.borrow()
.sibling
.clone();
if sibling.is_some() {
self.next_effect = sibling;
break;
}

let _return = self
.next_effect
.clone()
.unwrap()
.clone()
.borrow()
._return
.clone();

if _return.is_none() {
self.next_effect = None
} else {
self.next_effect = _return;
}
}
}
}
}

fn commit_mutation_effects_on_fiber(&self, finished_work: Rc<RefCell<FiberNode>>) {
let flags = finished_work.clone().borrow().flags.clone();
if flags.contains(Flags::Placement) {
self.commit_placement(finished_work.clone());
finished_work.clone().borrow_mut().flags -= Flags::Placement
}
}

fn commit_placement(&self, finished_work: Rc<RefCell<FiberNode>>) {
let host_parent = self.get_host_parent(finished_work.clone());
if host_parent.is_none() {
return;
}
let parent_state_node = FiberNode::derive_state_node(host_parent.unwrap());

if parent_state_node.is_some() {
self.append_placement_node_into_container(
finished_work.clone(),
parent_state_node.unwrap(),
);
}
}

fn get_element_from_state_node(&self, state_node: Rc<StateNode>) -> Rc<dyn Any> {
match &*state_node {
StateNode::FiberRootNode(root) => root.clone().borrow().container.clone(),
StateNode::Element(ele) => ele.clone(),
}
}

fn append_placement_node_into_container(
&self,
fiber: Rc<RefCell<FiberNode>>,
parent: Rc<dyn Any>,
) {
let fiber = fiber.clone();
let tag = fiber.borrow().tag.clone();
if tag == WorkTag::HostComponent || tag == WorkTag::HostText {
let state_node = fiber.clone().borrow().state_node.clone().unwrap();
self.host_config.append_child_to_container(
self.get_element_from_state_node(state_node),
parent.clone(),
);
return;
}

let child = fiber.borrow().child.clone();
if child.is_some() {
self.append_placement_node_into_container(child.clone().unwrap(), parent.clone());
let mut sibling = child.unwrap().clone().borrow().sibling.clone();
while sibling.is_some() {
self.append_placement_node_into_container(sibling.clone().unwrap(), parent.clone());
sibling = sibling.clone().unwrap().clone().borrow().sibling.clone();
}
}
}

fn get_host_parent(&self, fiber: Rc<RefCell<FiberNode>>) -> Option<Rc<RefCell<FiberNode>>> {
let mut parent = fiber.clone().borrow()._return.clone();
while parent.is_some() {
let p = parent.clone().unwrap();
let parent_tag = p.borrow().tag.clone();
if parent_tag == WorkTag::HostComponent || parent_tag == WorkTag::HostRoot {
return Some(p);
}
parent = p.borrow()._return.clone();
}

None
}
}
53 changes: 33 additions & 20 deletions packages/react-reconciler/src/complete_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use crate::fiber::{FiberNode, StateNode};
use crate::fiber_flags::Flags;
use crate::HostConfig;
use crate::work_tags::WorkTag;
use crate::work_tags::WorkTag::HostText;

pub struct CompleteWork {
pub host_config: Rc<dyn HostConfig>,
Expand All @@ -28,21 +27,24 @@ impl CompleteWork {
while node.is_some() {
let node_unwrap = node.clone().unwrap();
let n = node_unwrap.clone();
if n.borrow().tag == WorkTag::HostComponent || n.borrow().tag == HostText {
if n.borrow().tag == WorkTag::HostComponent || n.borrow().tag == WorkTag::HostText {
self.host_config.append_initial_child(
parent.clone(),
FiberNode::derive_state_node(node.clone().unwrap()).unwrap(),
)
} else if n.borrow().child.is_some() {
let n = node_unwrap.clone();
let borrowed = n.borrow_mut();
borrowed
.child
.as_ref()
.unwrap()
.clone()
.borrow_mut()
._return = Some(node_unwrap.clone());
{
let borrowed = n.borrow_mut();
borrowed
.child
.as_ref()
.unwrap()
.clone()
.borrow_mut()
._return = Some(node_unwrap.clone());
}

node = node_unwrap.clone().borrow().child.clone();
continue;
}
Expand All @@ -51,30 +53,41 @@ impl CompleteWork {
return;
}

while node_unwrap.borrow().sibling.clone().is_none() {
if node_unwrap.borrow()._return.is_none()
while node
.clone()
.unwrap()
.clone()
.borrow()
.sibling
.clone()
.is_none()
{
let node_cloned = node.clone().unwrap().clone();
if node_cloned.borrow()._return.is_none()
|| Rc::ptr_eq(
&node_unwrap
.borrow()
._return
.as_ref()
.unwrap(),
&node_cloned.borrow()._return.as_ref().unwrap(),
&work_in_progress,
)
{
return;
}

node_unwrap
.borrow_mut()
node = node_cloned.borrow()._return.clone();
}

{
node.clone()
.unwrap()
.borrow()
.sibling
.clone()
.unwrap()
.clone()
.borrow_mut()
._return = node_unwrap.borrow()._return.clone();
node = node_unwrap.borrow().sibling.clone();
}

node = node.clone().unwrap().borrow().sibling.clone();
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/fiber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,13 @@ impl FiberNode {
}

pub struct FiberRootNode {
pub container: Rc<JsValue>,
pub container: Rc<dyn Any>,
pub current: Rc<RefCell<FiberNode>>,
pub finished_work: Option<Rc<RefCell<FiberNode>>>,
}

impl FiberRootNode {
pub fn new(container: Rc<JsValue>, host_root_fiber: Rc<RefCell<FiberNode>>) -> Self {
pub fn new(container: Rc<dyn Any>, host_root_fiber: Rc<RefCell<FiberNode>>) -> Self {
Self {
container,
current: host_root_fiber,
Expand Down
5 changes: 3 additions & 2 deletions packages/react-reconciler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod work_loop;
mod begin_work;
mod child_fiber;
mod complete_work;
mod commit_work;

pub trait HostConfig {
fn create_text_instance(&self, content: String) -> Rc<dyn Any>;
Expand All @@ -33,10 +34,10 @@ impl Reconciler {
pub fn new(host_config: Rc<dyn HostConfig>) -> Self {
Reconciler { host_config }
}
pub fn create_container(&self, container: &JsValue) -> Rc<RefCell<FiberRootNode>> {
pub fn create_container(&self, container: Rc<dyn Any>) -> Rc<RefCell<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 root = Rc::new(RefCell::new(FiberRootNode::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()
Expand Down
Loading