Skip to content

Blog 7 #3

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

Open
wants to merge 8 commits into
base: blog-6
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
1 change: 1 addition & 0 deletions examples/hello-world/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"dayjs": "^1.11.10",
"react": "file://../../packages/react/pkg/react",
"react-dom": "file://../../packages/react-dom/pkg/react-dom",
"vite-plugin-wasm": "^3.3.0"
Expand Down
7 changes: 7 additions & 0 deletions examples/hello-world/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions examples/hello-world/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@


import dayjs from 'dayjs'

function App() {
return (
<div>a</div>
)
return (
<div><Comp>{dayjs().format()}</Comp></div>
)
}

function Comp({children}) {
return <span><i>{`Hello world, ${children}`}</i></span>
}

export default App
4 changes: 2 additions & 2 deletions examples/hello-world/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {createRoot} from 'react-dom'
import App from './App.tsx'

const comp = <div><p><span>Hello World</span></p></div>
const root = createRoot(document.getElementById("root"))
root.render(comp)
root.render(<App/>)

43 changes: 22 additions & 21 deletions packages/react-reconciler/src/begin_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,37 @@ use shared::derive_from_js_value;

use crate::child_fiber::{mount_child_fibers, reconcile_child_fibers};
use crate::fiber::FiberNode;
use crate::fiber_hooks::FiberHooks;
use crate::update_queue::process_update_queue;
use crate::work_tags::WorkTag;

pub fn begin_work(work_in_progress: Rc<RefCell<FiberNode>>) -> Option<Rc<RefCell<FiberNode>>> {
pub fn begin_work(work_in_progress: Rc<RefCell<FiberNode>>) -> Result<Option<Rc<RefCell<FiberNode>>>, JsValue> {
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
WorkTag::FunctionComponent => update_function_component(work_in_progress.clone()),
WorkTag::HostRoot => Ok(update_host_root(work_in_progress.clone())),
WorkTag::HostComponent => Ok(update_host_component(work_in_progress.clone())),
WorkTag::HostText => Ok(None),
};
}

pub fn update_host_root(
fn update_function_component(
work_in_progress: Rc<RefCell<FiberNode>>,
) -> Option<Rc<RefCell<FiberNode>>> {
) -> Result<Option<Rc<RefCell<FiberNode>>>, JsValue> {
let fiber_hooks = &mut FiberHooks::new();
let next_children = Rc::new(fiber_hooks.render_with_hooks(work_in_progress.clone())?);
reconcile_children(work_in_progress.clone(), Some(next_children));
Ok(work_in_progress.clone().borrow().child.clone())
}

fn update_host_root(work_in_progress: Rc<RefCell<FiberNode>>) -> Option<Rc<RefCell<FiberNode>>> {
process_update_queue(work_in_progress.clone());
let next_children = work_in_progress.clone().borrow().memoized_state.clone();
reconcile_children(work_in_progress.clone(), next_children);
work_in_progress.clone().borrow().child.clone()
}


pub fn update_host_component(
fn update_host_component(
work_in_progress: Rc<RefCell<FiberNode>>,
) -> Option<Rc<RefCell<FiberNode>>> {
let work_in_progress = Rc::clone(&work_in_progress);
Expand All @@ -46,22 +53,16 @@ pub fn update_host_component(
work_in_progress.clone().borrow().child.clone()
}

pub fn reconcile_children(work_in_progress: Rc<RefCell<FiberNode>>, children: Option<Rc<JsValue>>) {
fn reconcile_children(work_in_progress: Rc<RefCell<FiberNode>>, children: Option<Rc<JsValue>>) {
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,
)
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,
)
work_in_progress.borrow_mut().child =
mount_child_fibers(work_in_progress.clone(), None, children)
}
}
}
60 changes: 34 additions & 26 deletions packages/react-reconciler/src/complete_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@ use std::rc::Rc;
use wasm_bindgen::JsValue;
use web_sys::js_sys::Reflect;

use shared::log;

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 +25,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 +51,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 Expand Up @@ -107,10 +118,7 @@ impl CompleteWork {
let tag = { work_in_progress.clone().borrow().tag.clone() };
match tag {
WorkTag::FunctionComponent => {
log!(
"complete unknown fibler.tag {:?}",
work_in_progress.clone().borrow().tag
);
self.bubble_properties(work_in_progress.clone());
None
}
WorkTag::HostRoot => {
Expand Down
16 changes: 14 additions & 2 deletions packages/react-reconciler/src/fiber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,22 @@ impl Debug for FiberRootNode {

match current_ref.tag {
WorkTag::FunctionComponent => {
write!(f, "{:?}", current.borrow()._type.as_ref().unwrap());
let current_borrowed = current.borrow();
write!(
f,
"{:?}(flags:{:?}, subtreeFlags:{:?})",
current_borrowed._type.as_ref().unwrap(),
current_borrowed.flags,
current_borrowed.subtree_flags
);
}
WorkTag::HostRoot => {
write!(f, "{:?}(subtreeFlags:{:?})", WorkTag::HostRoot, current_ref.subtree_flags);
write!(
f,
"{:?}(subtreeFlags:{:?})",
WorkTag::HostRoot,
current_ref.subtree_flags
);
}
WorkTag::HostComponent => {
let current_borrowed = current.borrow();
Expand Down
57 changes: 57 additions & 0 deletions packages/react-reconciler/src/fiber_hooks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::cell::RefCell;
use std::rc::Rc;

use wasm_bindgen::{JsCast, JsValue};
use web_sys::js_sys::Function;

use shared::log;

use crate::fiber::FiberNode;

//
// use wasm_bindgen::JsValue;
//
// use crate::fiber::FiberNode;
// use crate::update_queue::UpdateQueue;
//
// pub struct Hook {
// memoized_state: Option<Rc<JsValue>>,
// update_queue: Option<Rc<RefCell<UpdateQueue>>>,
// next: Option<Rc<RefCell<Hook>>>,
// }
//
pub struct FiberHooks {
currently_rendering_fiber: Option<Rc<RefCell<FiberNode>>>,
}

impl FiberHooks {
pub fn new() -> Self {
FiberHooks {
currently_rendering_fiber: None
}
}

pub fn render_with_hooks(&mut self, work_in_progress: Rc<RefCell<FiberNode>>) -> Result<JsValue, JsValue> {
self.currently_rendering_fiber = Some(work_in_progress.clone());

let work_in_progress_cloned = work_in_progress.clone();
{
work_in_progress_cloned.borrow_mut().memoized_state = None;
work_in_progress_cloned.borrow_mut().update_queue = None;
}


let current = work_in_progress_cloned.borrow().alternate.clone();
if current.is_some() {
log!("还未实现update时renderWithHooks");
} else {}

let work_in_progress_borrow = work_in_progress_cloned.borrow();
let _type = work_in_progress_borrow._type.as_ref().unwrap();
let props = work_in_progress_borrow.pending_props.as_ref().unwrap();
let component = JsValue::dyn_ref::<Function>(_type).unwrap();
let children = component.call1(&JsValue::null(), props);
children
}
}

1 change: 1 addition & 0 deletions packages/react-reconciler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod begin_work;
mod child_fiber;
mod complete_work;
mod commit_work;
mod fiber_hooks;

pub trait HostConfig {
fn create_text_instance(&self, content: String) -> Rc<dyn Any>;
Expand Down
32 changes: 18 additions & 14 deletions packages/react-reconciler/src/work_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,15 @@ impl WorkLoop {
self.prepare_fresh_stack(Rc::clone(&root));

loop {
self.work_loop();
break;
match self.work_loop() {
Ok(_) => {
break;
}
Err(e) => {
log!("work_loop error {:?}", e);
self.work_in_progress = None;
}
};
}

log!("{:?}", *root.clone().borrow());
Expand All @@ -104,13 +111,8 @@ impl WorkLoop {
let finished_work = cloned.borrow().finished_work.clone().unwrap();
cloned.borrow_mut().finished_work = None;

let subtree_has_effect = get_mutation_mask().contains(
finished_work
.clone()
.borrow()
.subtree_flags
.clone(),
);
let subtree_has_effect =
get_mutation_mask().contains(finished_work.clone().borrow().subtree_flags.clone());
let root_has_effect =
get_mutation_mask().contains(finished_work.clone().borrow().flags.clone());

Expand All @@ -131,20 +133,22 @@ impl WorkLoop {
));
}

fn work_loop(&mut self) {
fn work_loop(&mut self) -> Result<(), JsValue> {
while self.work_in_progress.is_some() {
self.perform_unit_of_work(self.work_in_progress.clone().unwrap());
self.perform_unit_of_work(self.work_in_progress.clone().unwrap())?;
}
Ok(())
}

fn perform_unit_of_work(&mut self, fiber: Rc<RefCell<FiberNode>>) {
let next = begin_work(fiber.clone());
fn perform_unit_of_work(&mut self, fiber: Rc<RefCell<FiberNode>>) -> Result<(), JsValue> {
let next = begin_work(fiber.clone())?;

if next.is_none() {
self.complete_unit_of_work(fiber.clone())
self.complete_unit_of_work(fiber.clone());
} else {
self.work_in_progress = Some(next.unwrap());
}
Ok(())
}

fn complete_unit_of_work(&mut self, fiber: Rc<RefCell<FiberNode>>) {
Expand Down
Loading