From 459846062dbdf1f117bc71229f96beb276a46e41 Mon Sep 17 00:00:00 2001 From: youxingzhi Date: Wed, 10 Jul 2024 15:51:49 +0800 Subject: [PATCH 1/7] add two articles --- readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.md b/readme.md index 7815002..ec81a58 100644 --- a/readme.md +++ b/readme.md @@ -39,3 +39,7 @@ [从零实现 React v18,但 WASM 版 - [15] 实现 useEffect](https://www.paradeto.com/2024/05/24/big-react-wasm-15/) [从零实现 React v18,但 WASM 版 - [16] 实现 React Noop](https://www.paradeto.com/2024/06/06/big-react-wasm-16/) + +[从零实现 React v18,但 WASM 版 - [17] 实现 Concurrent 模式](https://www.paradeto.com/2024/06/19/big-react-wasm-17/) + +[从零实现 React v18,但 WASM 版 - [18] 实现 useRef, useCallback, useMemo](https://www.paradeto.com/2024/07/10/big-react-wasm-18/) From 95780737d2d826d4116c024be4758089ec3e1181 Mon Sep 17 00:00:00 2001 From: youxingzhi Date: Thu, 11 Jul 2024 20:36:48 +0800 Subject: [PATCH 2/7] bailout --- examples/hello-world/src/App.tsx | 2 +- examples/hello-world/src/perf/index.tsx | 27 ++++++ packages/react-reconciler/src/begin_work.rs | 86 ++++++++++++++++++- packages/react-reconciler/src/child_fiber.rs | 22 +++++ packages/react-reconciler/src/fiber.rs | 11 ++- packages/react-reconciler/src/fiber_hooks.rs | 15 ++-- packages/react-reconciler/src/fiber_lanes.rs | 8 ++ packages/react-reconciler/src/lib.rs | 5 +- packages/react-reconciler/src/update_queue.rs | 15 +++- packages/react-reconciler/src/work_loop.rs | 25 +++--- 10 files changed, 189 insertions(+), 27 deletions(-) create mode 100644 examples/hello-world/src/perf/index.tsx diff --git a/examples/hello-world/src/App.tsx b/examples/hello-world/src/App.tsx index 918688f..a9e1b84 100644 --- a/examples/hello-world/src/App.tsx +++ b/examples/hello-world/src/App.tsx @@ -1 +1 @@ -export {default} from './useCallback' +export {default} from './perf' diff --git a/examples/hello-world/src/perf/index.tsx b/examples/hello-world/src/perf/index.tsx new file mode 100644 index 0000000..860348d --- /dev/null +++ b/examples/hello-world/src/perf/index.tsx @@ -0,0 +1,27 @@ +import {useState} from 'react' + +function Child() { + console.log('Child Render') + return
Child
+} + +function Parent() { + const [n, setN] = useState(0) + console.log('Parent render') + return ( +
setN(1)}> + Parent + +
+ ) +} + +export default function App() { + console.log('App render') + return ( +
+ App + +
+ ) +} diff --git a/packages/react-reconciler/src/begin_work.rs b/packages/react-reconciler/src/begin_work.rs index d77842b..388e3fb 100644 --- a/packages/react-reconciler/src/begin_work.rs +++ b/packages/react-reconciler/src/begin_work.rs @@ -3,21 +3,97 @@ use std::rc::Rc; use wasm_bindgen::JsValue; -use shared::derive_from_js_value; +use shared::{derive_from_js_value, is_dev, log}; use web_sys::js_sys::Object; -use crate::child_fiber::{mount_child_fibers, reconcile_child_fibers}; +use crate::child_fiber::{clone_child_fiblers, mount_child_fibers, reconcile_child_fibers}; use crate::fiber::{FiberNode, MemoizedState}; use crate::fiber_flags::Flags; use crate::fiber_hooks::render_with_hooks; -use crate::fiber_lanes::Lane; +use crate::fiber_lanes::{include_some_lanes, Lane}; use crate::update_queue::{process_update_queue, ReturnOfProcessUpdateQueue}; use crate::work_tags::WorkTag; +static mut DID_RECEIVE_UPDATE: bool = false; + +pub fn mark_wip_received_update() { + unsafe { DID_RECEIVE_UPDATE = true }; +} + +fn bailout_on_already_finished_work( + wip: Rc>, + render_lane: Lane, +) -> Option>> { + // log!( + // "tag:{:?} child_lanes:{:?} render_lanes:{:?} result:{:?}", + // wip.borrow().tag, + // wip.borrow().child_lanes.clone(), + // render_lane, + // wip.borrow().child_lanes.clone() & render_lane.clone() + // ); + if !include_some_lanes(wip.borrow().child_lanes.clone(), render_lane) { + if is_dev() { + log!("bailout the whole subtree"); + } + return None; + } + if is_dev() { + log!("bailout current fiber"); + } + clone_child_fiblers(wip.clone()); + wip.borrow().child.clone() +} + +fn check_scheduled_update_or_context(current: Rc>, render_lane: Lane) -> bool { + let update_lanes = current.borrow().lanes.clone(); + if include_some_lanes(update_lanes, render_lane) { + return true; + } + false +} + pub fn begin_work( work_in_progress: Rc>, render_lane: Lane, ) -> Result>>, JsValue> { + unsafe { + DID_RECEIVE_UPDATE = false; + }; + let current = work_in_progress.borrow().alternate.clone(); + + if current.is_some() { + let current = current.unwrap(); + let old_props = current.borrow().memoized_props.clone(); + let old_type = current.borrow()._type.clone(); + let new_props = work_in_progress.borrow().pending_props.clone(); + let new_type = work_in_progress.borrow()._type.clone(); + if !Object::is(&old_props, &new_props) || !Object::is(&old_type, &new_type) { + unsafe { DID_RECEIVE_UPDATE = true } + } else { + let has_scheduled_update_or_context = + check_scheduled_update_or_context(current.clone(), render_lane.clone()); + // The current fiber lane is not included in render_lane + // TODO context + if !has_scheduled_update_or_context { + unsafe { DID_RECEIVE_UPDATE = false } + // // if current.is_some() { + // let c = current.clone(); + // log!( + // "current tag:{:?} lanes:{:?} child_lanes:{:?} render_lane:{:?}", + // c.borrow().tag, + // c.borrow().lanes, + // c.borrow().child_lanes, + // render_lane + // ); + // // } + return Ok(bailout_on_already_finished_work( + work_in_progress, + render_lane, + )); + } + } + } + let tag = work_in_progress.clone().borrow().tag.clone(); return match tag { WorkTag::FunctionComponent => { @@ -34,6 +110,10 @@ fn update_function_component( render_lane: Lane, ) -> Result>>, JsValue> { let next_children = render_with_hooks(work_in_progress.clone(), render_lane)?; + + // let current = work_in_progress.borrow().alternate.clone(); + // if current.is_some()&& !d + reconcile_children(work_in_progress.clone(), Some(next_children)); Ok(work_in_progress.clone().borrow().child.clone()) } diff --git a/packages/react-reconciler/src/child_fiber.rs b/packages/react-reconciler/src/child_fiber.rs index f2df818..965cf4c 100644 --- a/packages/react-reconciler/src/child_fiber.rs +++ b/packages/react-reconciler/src/child_fiber.rs @@ -398,6 +398,28 @@ fn _reconcile_child_fibers( delete_remaining_children(return_fiber, current_first_child, should_track_effects) } +pub fn clone_child_fiblers(wip: Rc>) { + if wip.borrow().child.is_none() { + return; + } + + let mut current_child = { wip.borrow().child.clone().unwrap() }; + let pending_props = { current_child.borrow().pending_props.clone() }; + let mut new_child = FiberNode::create_work_in_progress(current_child.clone(), pending_props); + wip.borrow_mut().child = Some(new_child.clone()); + new_child.borrow_mut()._return = Some(wip); + + while current_child.borrow().sibling.is_some() { + let sibling = { current_child.borrow().sibling.clone().unwrap() }; + let pending_props = { sibling.borrow().pending_props.clone() }; + let new_slibing = FiberNode::create_work_in_progress(sibling.clone(), pending_props); + new_child.borrow_mut().sibling = Some(new_slibing.clone()); + + current_child = sibling; + new_child = new_slibing; + } +} + pub fn reconcile_child_fibers( return_fiber: Rc>, current_first_child: Option>>, diff --git a/packages/react-reconciler/src/fiber.rs b/packages/react-reconciler/src/fiber.rs index f02cae9..a483fe9 100644 --- a/packages/react-reconciler/src/fiber.rs +++ b/packages/react-reconciler/src/fiber.rs @@ -47,6 +47,7 @@ impl MemoizedState { pub struct FiberNode { pub lanes: Lane, + pub child_lanes: Lane, pub index: u32, pub tag: WorkTag, pub pending_props: JsValue, @@ -131,6 +132,7 @@ impl FiberNode { subtree_flags: Flags::NoFlags, deletions: vec![], lanes: Lane::NoLane, + child_lanes: Lane::NoLane, _ref, } } @@ -177,7 +179,7 @@ impl FiberNode { return if w.is_none() { let wip = { - let c = c_rc.borrow(); + let c = { c_rc.borrow() }; let mut wip = FiberNode::new(c.tag.clone(), pending_props, c.key.clone(), c._ref.clone()); wip._type = c._type.clone(); @@ -186,6 +188,8 @@ impl FiberNode { wip.update_queue = c.update_queue.clone(); wip.flags = c.flags.clone(); wip.child = c.child.clone(); + wip.lanes = c.lanes.clone(); + wip.child_lanes = c.child_lanes.clone(); wip.memoized_props = c.memoized_props.clone(); wip.memoized_state = c.memoized_state.clone(); wip.alternate = Some(current); @@ -193,8 +197,7 @@ impl FiberNode { }; let wip_rc = Rc::new(RefCell::new(wip)); { - let mut fibler_node = c_rc.borrow_mut(); - fibler_node.alternate = Some(wip_rc.clone()); + c_rc.clone().borrow_mut().alternate = Some(wip_rc.clone()); } wip_rc } else { @@ -212,6 +215,8 @@ impl FiberNode { wip.update_queue = c.update_queue.clone(); wip.flags = c.flags.clone(); wip.child = c.child.clone(); + wip.lanes = c.lanes.clone(); + wip.child_lanes = c.child_lanes.clone(); wip.memoized_props = c.memoized_props.clone(); wip.memoized_state = c.memoized_state.clone(); wip._ref = c._ref.clone(); diff --git a/packages/react-reconciler/src/fiber_hooks.rs b/packages/react-reconciler/src/fiber_hooks.rs index 3e041ec..ee71f7a 100644 --- a/packages/react-reconciler/src/fiber_hooks.rs +++ b/packages/react-reconciler/src/fiber_hooks.rs @@ -9,7 +9,7 @@ use shared::log; use crate::fiber::{FiberNode, MemoizedState}; use crate::fiber_flags::Flags; -use crate::fiber_lanes::{merge_lanes, request_update_lane, Lane}; +use crate::fiber_lanes::{merge_lanes, remove_lanes, request_update_lane, Lane}; use crate::update_queue::{ create_update, create_update_queue, enqueue_update, process_update_queue, ReturnOfProcessUpdateQueue, Update, UpdateQueue, @@ -83,6 +83,13 @@ impl Hook { } } +fn bailout_hook(wip: Rc>, render_lane: Lane) { + let current = { wip.borrow().alternate.clone().unwrap() }; + wip.borrow_mut().update_queue = current.borrow().update_queue.clone(); + wip.borrow_mut().flags -= Flags::PassiveEffect; + current.borrow_mut().lanes = remove_lanes(current.borrow().lanes.clone(), render_lane); +} + fn update_hooks_to_dispatcher(is_update: bool) { let object = Object::new(); @@ -428,10 +435,8 @@ fn dispatch_set_state( ) { let lane = request_update_lane(); let update = create_update(action.clone(), lane.clone()); - enqueue_update(update_queue.clone(), update); - unsafe { - schedule_update_on_fiber(fiber.clone(), lane); - } + enqueue_update(update_queue.clone(), update, fiber.clone(), lane.clone()); + schedule_update_on_fiber(fiber.clone(), lane); } fn create_fc_update_queue() -> Rc> { diff --git a/packages/react-reconciler/src/fiber_lanes.rs b/packages/react-reconciler/src/fiber_lanes.rs index 96e5337..916419f 100644 --- a/packages/react-reconciler/src/fiber_lanes.rs +++ b/packages/react-reconciler/src/fiber_lanes.rs @@ -60,3 +60,11 @@ pub fn lanes_to_scheduler_priority(lanes: Lane) -> Priority { } Priority::IdlePriority } + +pub fn include_some_lanes(set: Lane, subset: Lane) -> bool { + return (set & subset) != Lane::NoLane; +} + +pub fn remove_lanes(set: Lane, subset: Lane) -> Lane { + return set - subset; +} diff --git a/packages/react-reconciler/src/lib.rs b/packages/react-reconciler/src/lib.rs index 454510a..81e8d52 100644 --- a/packages/react-reconciler/src/lib.rs +++ b/packages/react-reconciler/src/lib.rs @@ -74,9 +74,12 @@ impl Reconciler { let host_root_fiber = Rc::clone(&root).borrow().current.clone(); let root_render_priority = Lane::SyncLane; let update = create_update(element.clone(), root_render_priority.clone()); + let update_queue = { host_root_fiber.borrow().update_queue.clone().unwrap() }; enqueue_update( - host_root_fiber.borrow().update_queue.clone().unwrap(), + update_queue, update, + host_root_fiber.clone(), + root_render_priority.clone(), ); unsafe { HOST_CONFIG = Some(self.host_config.clone()); diff --git a/packages/react-reconciler/src/update_queue.rs b/packages/react-reconciler/src/update_queue.rs index 46d7763..31ea240 100644 --- a/packages/react-reconciler/src/update_queue.rs +++ b/packages/react-reconciler/src/update_queue.rs @@ -40,7 +40,12 @@ pub fn create_update(action: JsValue, lane: Lane) -> Update { } } -pub fn enqueue_update(update_queue: Rc>, mut update: Update) { +pub fn enqueue_update( + update_queue: Rc>, + mut update: Update, + fiber: Rc>, + lane: Lane, +) { let pending = update_queue.borrow().shared.pending.clone(); let update_rc = Rc::new(RefCell::new(update)); let update_option = Option::from(update_rc.clone()); @@ -52,6 +57,14 @@ pub fn enqueue_update(update_queue: Rc>, mut update: Update pending.borrow_mut().next = update_option.clone(); } update_queue.borrow_mut().shared.pending = update_option.clone(); + + let fiber_lane = { fiber.borrow().lanes.clone() }; + fiber.borrow_mut().lanes = merge_lanes(fiber_lane, lane.clone()); + let alternate = fiber.borrow().alternate.clone(); + if alternate.is_some() { + let alternate = alternate.unwrap(); + alternate.borrow_mut().lanes = merge_lanes(alternate.borrow().lanes.clone(), lane); + } } pub fn create_update_queue() -> Rc> { diff --git a/packages/react-reconciler/src/work_loop.rs b/packages/react-reconciler/src/work_loop.rs index 40bcab6..1cdb516 100644 --- a/packages/react-reconciler/src/work_loop.rs +++ b/packages/react-reconciler/src/work_loop.rs @@ -68,27 +68,26 @@ pub fn mark_update_lane_from_fiber_to_root( let mut node = Rc::clone(&fiber); let mut parent = Rc::clone(&fiber).borrow()._return.clone(); - let node_lanes = { node.borrow().lanes.clone() }; - node.borrow_mut().lanes = merge_lanes(node_lanes, lane.clone()); - let alternate = node.borrow().alternate.clone(); - if alternate.is_some() { - let alternate = alternate.unwrap(); - let alternate_lanes = { alternate.borrow().lanes.clone() }; - alternate.borrow_mut().lanes = merge_lanes(alternate_lanes, lane); - } - while parent.is_some() { + let p = parent.clone().unwrap(); + let child_lanes = { p.borrow().child_lanes.clone() }; + p.borrow_mut().child_lanes = merge_lanes(child_lanes, lane.clone()); + + let alternate = p.borrow().alternate.clone(); + if alternate.is_some() { + let alternate = alternate.unwrap(); + let child_lanes = { alternate.borrow().child_lanes.clone() }; + alternate.borrow_mut().child_lanes = merge_lanes(child_lanes, lane.clone()); + } + node = parent.clone().unwrap(); - let rc = Rc::clone(&parent.unwrap()); - let rc_ref = rc.borrow(); - let next = match rc_ref._return.as_ref() { + parent = match parent.clone().unwrap().borrow()._return.as_ref() { None => None, Some(node) => { let a = node.clone(); Some(a) } }; - parent = next; } let fiber_node_rc = Rc::clone(&node); From 5b2581ce90713c89c1cca2894842b4b76f4a196d Mon Sep 17 00:00:00 2001 From: youxingzhi Date: Fri, 19 Jul 2024 15:45:24 +0800 Subject: [PATCH 3/7] fix reconcile_children_array --- examples/hello-world/src/perf/index.tsx | 32 +++++++++---------- packages/react-reconciler/src/child_fiber.rs | 3 +- .../react-reconciler/src/complete_work.rs | 6 ++-- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/examples/hello-world/src/perf/index.tsx b/examples/hello-world/src/perf/index.tsx index 860348d..92eb8ba 100644 --- a/examples/hello-world/src/perf/index.tsx +++ b/examples/hello-world/src/perf/index.tsx @@ -1,27 +1,27 @@ import {useState} from 'react' -function Child() { +function Child({num}) { console.log('Child Render') - return
Child
+ return
Child {num}
} -function Parent() { - const [n, setN] = useState(0) +export default function Parent() { + const [num, setNum] = useState(1) console.log('Parent render') return ( -
setN(1)}> - Parent - +
setNum(2)}> + Parent {num} +
) } -export default function App() { - console.log('App render') - return ( -
- App - -
- ) -} +// export default function App() { +// console.log('App render') +// return ( +//
+// App +// +//
+// ) +// } diff --git a/packages/react-reconciler/src/child_fiber.rs b/packages/react-reconciler/src/child_fiber.rs index 965cf4c..20aaad5 100644 --- a/packages/react-reconciler/src/child_fiber.rs +++ b/packages/react-reconciler/src/child_fiber.rs @@ -212,7 +212,7 @@ fn update_from_map( should_track_effects: bool, ) -> Option>> { let key_to_use; - if type_of(element, "string") || type_of(element, "null") { + if type_of(element, "string") || type_of(element, "null") || type_of(element, "number") { key_to_use = JsValue::from(index); } else { let key = derive_from_js_value(element, "key"); @@ -268,7 +268,6 @@ fn update_from_map( element, )))); } - // panic!("update_from_map unsupported"); None } diff --git a/packages/react-reconciler/src/complete_work.rs b/packages/react-reconciler/src/complete_work.rs index fdfb179..2e004a5 100644 --- a/packages/react-reconciler/src/complete_work.rs +++ b/packages/react-reconciler/src/complete_work.rs @@ -140,6 +140,8 @@ impl CompleteWork { WorkTag::HostComponent => { if current.is_some() && work_in_progress_cloned.borrow().state_node.is_some() { log!("update properties"); + // todo compare + // CompleteWork::mark_update(work_in_progress.clone()); let current = current.unwrap(); if !Object::is( ¤t.borrow()._ref, @@ -175,8 +177,8 @@ impl CompleteWork { ¤t.clone().unwrap().clone().borrow().memoized_props, "content", ); - let new_test = derive_from_js_value(&new_props, "content"); - if !Object::is(&old_text, &new_test) { + let new_text = derive_from_js_value(&new_props, "content"); + if !Object::is(&old_text, &new_text) { CompleteWork::mark_update(work_in_progress.clone()); } } else { From 91780ef2bc9e40b0bf800f49b3ba8eb086991641 Mon Sep 17 00:00:00 2001 From: youxingzhi Date: Fri, 19 Jul 2024 17:16:26 +0800 Subject: [PATCH 4/7] fix clone childs --- examples/hello-world/src/perf/index.tsx | 25 +++++++++++-------- packages/react-reconciler/src/begin_work.rs | 4 +-- packages/react-reconciler/src/child_fiber.rs | 22 +++++++++++++--- packages/react-reconciler/src/commit_work.rs | 2 ++ .../react-reconciler/src/complete_work.rs | 25 ++++++++++++++++++- packages/react-reconciler/src/update_queue.rs | 3 ++- packages/react-reconciler/src/work_loop.rs | 2 +- 7 files changed, 63 insertions(+), 20 deletions(-) diff --git a/examples/hello-world/src/perf/index.tsx b/examples/hello-world/src/perf/index.tsx index 92eb8ba..2cc1737 100644 --- a/examples/hello-world/src/perf/index.tsx +++ b/examples/hello-world/src/perf/index.tsx @@ -5,23 +5,26 @@ function Child({num}) { return
Child {num}
} -export default function Parent() { +function Parent() { const [num, setNum] = useState(1) console.log('Parent render') return (
setNum(2)}> - Parent {num}
+ //
setNum(2)}> + // Parent {num} + // + //
) } -// export default function App() { -// console.log('App render') -// return ( -//
-// App -// -//
-// ) -// } +export default function App() { + console.log('App render') + return ( +
+ App + +
+ ) +} diff --git a/packages/react-reconciler/src/begin_work.rs b/packages/react-reconciler/src/begin_work.rs index 388e3fb..1dd332d 100644 --- a/packages/react-reconciler/src/begin_work.rs +++ b/packages/react-reconciler/src/begin_work.rs @@ -33,12 +33,12 @@ fn bailout_on_already_finished_work( // ); if !include_some_lanes(wip.borrow().child_lanes.clone(), render_lane) { if is_dev() { - log!("bailout the whole subtree"); + log!("bailout the whole subtree {:?}", wip); } return None; } if is_dev() { - log!("bailout current fiber"); + log!("bailout current fiber {:?}", wip); } clone_child_fiblers(wip.clone()); wip.borrow().child.clone() diff --git a/packages/react-reconciler/src/child_fiber.rs b/packages/react-reconciler/src/child_fiber.rs index 20aaad5..5d996e2 100644 --- a/packages/react-reconciler/src/child_fiber.rs +++ b/packages/react-reconciler/src/child_fiber.rs @@ -182,6 +182,7 @@ fn reconcile_single_text_node( Rc::new(RefCell::new(created)) } +#[derive(Clone, Debug)] struct Key(JsValue); impl PartialEq for Key { @@ -224,6 +225,7 @@ fn update_from_map( let before = existing_children.get(&Key(key_to_use.clone())).clone(); if type_of(element, "null") || type_of(element, "string") || type_of(element, "number") { let props = create_props_with_content(element.clone()); + // log!("update_from_map {:?}", props); if before.is_some() { let before = (*before.clone().unwrap()).clone(); existing_children.remove(&Key(key_to_use.clone())); @@ -295,10 +297,11 @@ fn reconcile_children_array( existing_children.insert(Key(key_to_use), current_rc.clone()); current = current_rc.borrow().sibling.clone(); } - + // log!("existing_children {:?}", existing_children.keys()); let length = new_child.length(); for i in 0..length { let after = new_child.get(i); + // log!("after {:?}", after); let new_fiber = update_from_map( return_fiber.clone(), &mut existing_children, @@ -306,7 +309,7 @@ fn reconcile_children_array( &after, should_track_effects, ); - + // log!("new_fiber {:?}", new_fiber); if new_fiber.is_none() { continue; } @@ -347,7 +350,11 @@ fn reconcile_children_array( for (_, fiber) in existing_children { delete_child(return_fiber.clone(), fiber, should_track_effects); } - + log!( + "first_new_fiber {:?} {:?}", + first_new_fiber, + first_new_fiber.clone().unwrap().borrow().sibling + ); first_new_fiber } @@ -406,12 +413,19 @@ pub fn clone_child_fiblers(wip: Rc>) { let pending_props = { current_child.borrow().pending_props.clone() }; let mut new_child = FiberNode::create_work_in_progress(current_child.clone(), pending_props); wip.borrow_mut().child = Some(new_child.clone()); - new_child.borrow_mut()._return = Some(wip); + new_child.borrow_mut()._return = Some(wip.clone()); while current_child.borrow().sibling.is_some() { let sibling = { current_child.borrow().sibling.clone().unwrap() }; let pending_props = { sibling.borrow().pending_props.clone() }; let new_slibing = FiberNode::create_work_in_progress(sibling.clone(), pending_props); + new_slibing.borrow_mut()._return = Some(wip.clone()); + // log!( + // "new {:?} {:?} {:?}", + // new_slibing, + // new_slibing.borrow()._return, + // sibling.borrow()._return + // ); new_child.borrow_mut().sibling = Some(new_slibing.clone()); current_child = sibling; diff --git a/packages/react-reconciler/src/commit_work.rs b/packages/react-reconciler/src/commit_work.rs index b3739c8..f550fc5 100644 --- a/packages/react-reconciler/src/commit_work.rs +++ b/packages/react-reconciler/src/commit_work.rs @@ -222,6 +222,7 @@ fn commit_mutation_effects_on_fiber( finished_work.borrow_mut().flags -= Flags::ChildDeletion; } + log!("finished_work {:?}", finished_work); if flags.contains(Flags::Update) { commit_update(finished_work.clone()); finished_work.borrow_mut().flags -= Flags::Update; @@ -285,6 +286,7 @@ fn commit_update(finished_work: Rc>) { WorkTag::HostText => { let new_content = derive_from_js_value(&cloned.borrow().pending_props, "content"); let state_node = FiberNode::derive_state_node(finished_work.clone()); + log!("commit_update {:?} {:?}", state_node, new_content); if let Some(state_node) = state_node.clone() { unsafe { HOST_CONFIG diff --git a/packages/react-reconciler/src/complete_work.rs b/packages/react-reconciler/src/complete_work.rs index 2e004a5..415e9bf 100644 --- a/packages/react-reconciler/src/complete_work.rs +++ b/packages/react-reconciler/src/complete_work.rs @@ -9,6 +9,7 @@ use shared::{derive_from_js_value, log}; use crate::fiber::{FiberNode, StateNode}; use crate::fiber_flags::Flags; +use crate::fiber_lanes::{merge_lanes, Lane}; use crate::work_tags::WorkTag; use crate::HostConfig; @@ -97,14 +98,24 @@ impl CompleteWork { fn bubble_properties(&self, complete_work: Rc>) { let mut subtree_flags = Flags::NoFlags; + let mut new_child_lanes = Lane::NoLane; { let mut child = complete_work.clone().borrow().child.clone(); + while child.is_some() { let child_rc = child.clone().unwrap().clone(); { let child_borrowed = child_rc.borrow(); subtree_flags |= child_borrowed.subtree_flags.clone(); subtree_flags |= child_borrowed.flags.clone(); + + new_child_lanes = merge_lanes( + new_child_lanes, + merge_lanes( + child_borrowed.lanes.clone(), + child_borrowed.child_lanes.clone(), + ), + ) } { child_rc.borrow_mut()._return = Some(complete_work.clone()); @@ -114,6 +125,7 @@ impl CompleteWork { } complete_work.clone().borrow_mut().subtree_flags |= subtree_flags.clone(); + complete_work.clone().borrow_mut().child_lanes |= new_child_lanes.clone(); } fn mark_update(fiber: Rc>) { @@ -131,15 +143,16 @@ impl CompleteWork { match tag { WorkTag::FunctionComponent => { self.bubble_properties(work_in_progress.clone()); + // log!("bubble_properties function {:?}", work_in_progress.clone()); None } WorkTag::HostRoot => { self.bubble_properties(work_in_progress.clone()); + // log!("bubble_properties HostRoot {:?}", work_in_progress.clone()); None } WorkTag::HostComponent => { if current.is_some() && work_in_progress_cloned.borrow().state_node.is_some() { - log!("update properties"); // todo compare // CompleteWork::mark_update(work_in_progress.clone()); let current = current.unwrap(); @@ -169,6 +182,10 @@ impl CompleteWork { } self.bubble_properties(work_in_progress.clone()); + // log!( + // "bubble_properties HostComponent {:?}", + // work_in_progress.clone() + // ); None } WorkTag::HostText => { @@ -178,6 +195,12 @@ impl CompleteWork { "content", ); let new_text = derive_from_js_value(&new_props, "content"); + // log!( + // "complete host {:?} {:?} {:?}", + // work_in_progress_cloned, + // old_text, + // new_text + // ); if !Object::is(&old_text, &new_text) { CompleteWork::mark_update(work_in_progress.clone()); } diff --git a/packages/react-reconciler/src/update_queue.rs b/packages/react-reconciler/src/update_queue.rs index 31ea240..4a47c0d 100644 --- a/packages/react-reconciler/src/update_queue.rs +++ b/packages/react-reconciler/src/update_queue.rs @@ -63,7 +63,8 @@ pub fn enqueue_update( let alternate = fiber.borrow().alternate.clone(); if alternate.is_some() { let alternate = alternate.unwrap(); - alternate.borrow_mut().lanes = merge_lanes(alternate.borrow().lanes.clone(), lane); + let lanes = { alternate.borrow().lanes.clone() }; + alternate.borrow_mut().lanes = merge_lanes(lanes, lane); } } diff --git a/packages/react-reconciler/src/work_loop.rs b/packages/react-reconciler/src/work_loop.rs index 1cdb516..0f710e9 100644 --- a/packages/react-reconciler/src/work_loop.rs +++ b/packages/react-reconciler/src/work_loop.rs @@ -489,7 +489,7 @@ fn complete_unit_of_work(fiber: Rc>) { } let _return = node.clone().unwrap().clone().borrow()._return.clone(); - + // log!("complete_unit_of_work {:?} {:?}", node, _return); if _return.is_none() { // node = None; // self.work_in_progress = None; From f3c493b6a1fcb417c85baabf2ca929a7dd4957fa Mon Sep 17 00:00:00 2001 From: youxingzhi Date: Fri, 19 Jul 2024 19:06:25 +0800 Subject: [PATCH 5/7] fix eager state bugs --- examples/hello-world/src/perf/index.tsx | 2 + packages/react-reconciler/src/begin_work.rs | 18 ++- packages/react-reconciler/src/commit_work.rs | 6 +- packages/react-reconciler/src/fiber.rs | 5 +- packages/react-reconciler/src/fiber_hooks.rs | 120 +++++++++++----- packages/react-reconciler/src/update_queue.rs | 135 +++++++++++++----- 6 files changed, 210 insertions(+), 76 deletions(-) diff --git a/examples/hello-world/src/perf/index.tsx b/examples/hello-world/src/perf/index.tsx index 2cc1737..28e779c 100644 --- a/examples/hello-world/src/perf/index.tsx +++ b/examples/hello-world/src/perf/index.tsx @@ -28,3 +28,5 @@ export default function App() {
) } + +//https://juejin.cn/post/7073692220313829407?searchId=20240719185830A176472F8B81316DB83C diff --git a/packages/react-reconciler/src/begin_work.rs b/packages/react-reconciler/src/begin_work.rs index 1dd332d..82a2a8e 100644 --- a/packages/react-reconciler/src/begin_work.rs +++ b/packages/react-reconciler/src/begin_work.rs @@ -9,7 +9,7 @@ use web_sys::js_sys::Object; use crate::child_fiber::{clone_child_fiblers, mount_child_fibers, reconcile_child_fibers}; use crate::fiber::{FiberNode, MemoizedState}; use crate::fiber_flags::Flags; -use crate::fiber_hooks::render_with_hooks; +use crate::fiber_hooks::{bailout_hook, render_with_hooks}; use crate::fiber_lanes::{include_some_lanes, Lane}; use crate::update_queue::{process_update_queue, ReturnOfProcessUpdateQueue}; use crate::work_tags::WorkTag; @@ -94,6 +94,8 @@ pub fn begin_work( } } + work_in_progress.borrow_mut().lanes = Lane::NoLane; + let tag = work_in_progress.clone().borrow().tag.clone(); return match tag { WorkTag::FunctionComponent => { @@ -109,10 +111,16 @@ fn update_function_component( work_in_progress: Rc>, render_lane: Lane, ) -> Result>>, JsValue> { - let next_children = render_with_hooks(work_in_progress.clone(), render_lane)?; + let next_children = render_with_hooks(work_in_progress.clone(), render_lane.clone())?; - // let current = work_in_progress.borrow().alternate.clone(); - // if current.is_some()&& !d + let current = work_in_progress.borrow().alternate.clone(); + if current.is_some() && unsafe { !DID_RECEIVE_UPDATE } { + bailout_hook(work_in_progress.clone(), render_lane.clone()); + return Ok(bailout_on_already_finished_work( + work_in_progress, + render_lane, + )); + } reconcile_children(work_in_progress.clone(), Some(next_children)); Ok(work_in_progress.clone().borrow().child.clone()) @@ -141,7 +149,7 @@ fn update_host_root( { let ReturnOfProcessUpdateQueue { memoized_state, .. } = - process_update_queue(base_state, pending, render_lane); + process_update_queue(base_state, pending, render_lane, None); work_in_progress.clone().borrow_mut().memoized_state = memoized_state; } diff --git a/packages/react-reconciler/src/commit_work.rs b/packages/react-reconciler/src/commit_work.rs index f550fc5..96ac6fe 100644 --- a/packages/react-reconciler/src/commit_work.rs +++ b/packages/react-reconciler/src/commit_work.rs @@ -222,7 +222,11 @@ fn commit_mutation_effects_on_fiber( finished_work.borrow_mut().flags -= Flags::ChildDeletion; } - log!("finished_work {:?}", finished_work); + // log!( + // "finished_work {:?} {:?}", + // finished_work, + // finished_work.borrow().alternate + // ); if flags.contains(Flags::Update) { commit_update(finished_work.clone()); finished_work.borrow_mut().flags -= Flags::Update; diff --git a/packages/react-reconciler/src/fiber.rs b/packages/react-reconciler/src/fiber.rs index a483fe9..d29bc6e 100644 --- a/packages/react-reconciler/src/fiber.rs +++ b/packages/react-reconciler/src/fiber.rs @@ -73,10 +73,11 @@ impl Debug for FiberNode { WorkTag::FunctionComponent => { write!( f, - "{:?}(flags:{:?}, subtreeFlags:{:?})", + "{:?}(flags:{:?}, subtreeFlags:{:?}, lanes:{:?})", self._type.as_ref(), self.flags, - self.subtree_flags + self.subtree_flags, + self.lanes ) .expect("print error"); } diff --git a/packages/react-reconciler/src/fiber_hooks.rs b/packages/react-reconciler/src/fiber_hooks.rs index ee71f7a..4dc5a2c 100644 --- a/packages/react-reconciler/src/fiber_hooks.rs +++ b/packages/react-reconciler/src/fiber_hooks.rs @@ -5,8 +5,9 @@ use wasm_bindgen::prelude::{wasm_bindgen, Closure}; use wasm_bindgen::{JsCast, JsValue}; use web_sys::js_sys::{Array, Function, Object, Reflect}; -use shared::log; +use shared::{is_dev, log}; +use crate::begin_work::mark_wip_received_update; use crate::fiber::{FiberNode, MemoizedState}; use crate::fiber_flags::Flags; use crate::fiber_lanes::{merge_lanes, remove_lanes, request_update_lane, Lane}; @@ -83,11 +84,13 @@ impl Hook { } } -fn bailout_hook(wip: Rc>, render_lane: Lane) { +pub fn bailout_hook(wip: Rc>, render_lane: Lane) { let current = { wip.borrow().alternate.clone().unwrap() }; - wip.borrow_mut().update_queue = current.borrow().update_queue.clone(); + let update_queue = { current.borrow().update_queue.clone() }; + let lanes = { current.borrow().lanes.clone() }; + wip.borrow_mut().update_queue = update_queue; wip.borrow_mut().flags -= Flags::PassiveEffect; - current.borrow_mut().lanes = remove_lanes(current.borrow().lanes.clone(), render_lane); + current.borrow_mut().lanes = remove_lanes(lanes, render_lane); } fn update_hooks_to_dispatcher(is_update: bool) { @@ -342,7 +345,7 @@ fn mount_state(initial_state: &JsValue) -> Result, JsValue> { closure.forget(); queue.clone().borrow_mut().dispatch = Some(function.clone()); - + queue.clone().borrow_mut().last_rendered_state = Some(memoized_state.clone()); Ok(vec![memoized_state, function.into()]) } @@ -386,31 +389,47 @@ fn update_state(_: &JsValue) -> Result, JsValue> { } if base_queue.is_some() { - log!("base state is {:?}", base_state); + let pre_state = hook.as_ref().unwrap().borrow().memoized_state.clone(); + let ReturnOfProcessUpdateQueue { memoized_state, base_state: new_base_state, base_queue: new_base_queue, - skipped_update_lanes, - } = process_update_queue(base_state, base_queue, unsafe { RENDER_LANE.clone() }); - unsafe { - let lanes = { - CURRENTLY_RENDERING_FIBER - .clone() - .unwrap() - .borrow() - .lanes - .clone() - }; - CURRENTLY_RENDERING_FIBER - .clone() - .unwrap() - .borrow_mut() - .lanes = merge_lanes(lanes, skipped_update_lanes) - }; - hook_cloned.borrow_mut().memoized_state = memoized_state; + } = process_update_queue( + base_state, + base_queue, + unsafe { RENDER_LANE.clone() }, + Some(|update: Rc>| { + let skipped_lane = update.borrow().lane.clone(); + let fiber = unsafe { CURRENTLY_RENDERING_FIBER.clone().unwrap().clone() }; + let lanes = { fiber.borrow().lanes.clone() }; + fiber.borrow_mut().lanes = merge_lanes(lanes, skipped_lane); + }), + ); + + if !(memoized_state.is_none() && pre_state.is_none()) { + let memoized_state = memoized_state.clone().unwrap(); + let pre_state = pre_state.unwrap(); + if let MemoizedState::MemoizedJsValue(ms_value) = memoized_state { + if let MemoizedState::MemoizedJsValue(ps_value) = pre_state { + if !Object::is(&ms_value, &ps_value) { + mark_wip_received_update(); + } + } + } + } + + hook_cloned.borrow_mut().memoized_state = memoized_state.clone(); hook_cloned.borrow_mut().base_state = new_base_state; hook_cloned.borrow_mut().base_queue = new_base_queue; + + queue.clone().unwrap().borrow_mut().last_rendered_state = Some(match memoized_state { + Some(m) => match m { + MemoizedState::MemoizedJsValue(js_value) => js_value, + _ => todo!(), + }, + None => todo!(), + }); } Ok(vec![ @@ -428,23 +447,60 @@ fn update_state(_: &JsValue) -> Result, JsValue> { ]) } +pub fn basic_state_reducer(state: &JsValue, action: &JsValue) -> Result { + if action.is_function() { + let function = action.dyn_ref::().unwrap(); + return function.call1(&JsValue::null(), state); + } + Ok(action.into()) +} + fn dispatch_set_state( fiber: Rc>, update_queue: Rc>, action: &JsValue, ) { let lane = request_update_lane(); - let update = create_update(action.clone(), lane.clone()); + let mut update = create_update(action.clone(), lane.clone()); + let current = { fiber.borrow().alternate.clone() }; + log!( + "dispatch_set_state {:?} {:?}", + fiber.borrow().lanes.clone(), + if current.is_none() { + Lane::NoLane + } else { + current.clone().unwrap().borrow().lanes.clone() + } + ); + if fiber.borrow().lanes == Lane::NoLane + && (current.is_none() || current.unwrap().borrow().lanes == Lane::NoLane) + { + log!("sdadgasd"); + let current_state = update_queue.borrow().last_rendered_state.clone(); + if current_state.is_none() { + panic!("current state is none") + } + let current_state = current_state.unwrap(); + let eager_state = basic_state_reducer(¤t_state, &action); + // if not ok, the update will be handled in render phase, means the error will be handled in render phase + if eager_state.is_ok() { + let eager_state = eager_state.unwrap(); + update.has_eager_state = true; + update.eager_state = Some(eager_state.clone()); + if Object::is(¤t_state, &eager_state) { + enqueue_update(update_queue.clone(), update, fiber.clone(), lane.clone()); + if is_dev() { + log!("Hit eager state") + } + return; + } + } + } + enqueue_update(update_queue.clone(), update, fiber.clone(), lane.clone()); schedule_update_on_fiber(fiber.clone(), lane); } -fn create_fc_update_queue() -> Rc> { - let update_queue = create_update_queue(); - update_queue.borrow_mut().last_effect = None; - update_queue -} - fn push_effect( hook_flags: Flags, create: Function, @@ -457,7 +513,7 @@ fn push_effect( let fiber = unsafe { CURRENTLY_RENDERING_FIBER.clone().unwrap() }; let update_queue = { fiber.borrow().update_queue.clone() }; if update_queue.is_none() { - let update_queue = create_fc_update_queue(); + let update_queue = create_update_queue(); fiber.borrow_mut().update_queue = Some(update_queue.clone()); effect.borrow_mut().next = Option::from(effect.clone()); update_queue.borrow_mut().last_effect = Option::from(effect.clone()); diff --git a/packages/react-reconciler/src/update_queue.rs b/packages/react-reconciler/src/update_queue.rs index 4a47c0d..4c804d3 100644 --- a/packages/react-reconciler/src/update_queue.rs +++ b/packages/react-reconciler/src/update_queue.rs @@ -7,7 +7,7 @@ use web_sys::js_sys::Function; use shared::log; use crate::fiber::{FiberNode, MemoizedState}; -use crate::fiber_hooks::Effect; +use crate::fiber_hooks::{basic_state_reducer, Effect}; use crate::fiber_lanes::{is_subset_of_lanes, merge_lanes, Lane}; #[derive(Clone, Debug)] @@ -18,6 +18,8 @@ pub struct Update { pub action: Option, pub lane: Lane, pub next: Option>>, + pub has_eager_state: bool, + pub eager_state: Option, } #[derive(Clone, Debug)] @@ -30,6 +32,7 @@ pub struct UpdateQueue { pub shared: UpdateType, pub dispatch: Option, pub last_effect: Option>>, + pub last_rendered_state: Option, } pub fn create_update(action: JsValue, lane: Lane) -> Update { @@ -37,6 +40,8 @@ pub fn create_update(action: JsValue, lane: Lane) -> Update { action: Some(action), lane, next: None, + has_eager_state: false, + eager_state: None, } } @@ -73,6 +78,7 @@ pub fn create_update_queue() -> Rc> { shared: UpdateType { pending: None }, dispatch: None, last_effect: None, + last_rendered_state: None, })) } @@ -80,32 +86,35 @@ pub struct ReturnOfProcessUpdateQueue { pub memoized_state: Option, pub base_state: Option, pub base_queue: Option>>, - pub skipped_update_lanes: Lane, } pub fn process_update_queue( base_state: Option, pending_update: Option>>, render_lanes: Lane, + on_skip_update: Option>) -> ()>, ) -> ReturnOfProcessUpdateQueue { let mut result = ReturnOfProcessUpdateQueue { memoized_state: base_state.clone(), base_state: base_state.clone(), base_queue: None, - skipped_update_lanes: Lane::NoLane, }; if pending_update.is_some() { - let mut update_option = pending_update.clone(); + let update_option = pending_update.clone().unwrap(); + let first = update_option.borrow().next.clone(); + let mut pending = update_option.borrow().next.clone(); + // 更新后的baseState(有跳过情况下与memoizedState不同) - let mut new_base_state: Option = base_state; + let mut new_base_state: Option = base_state.clone(); // 更新后的baseQueue第一个节点 let mut new_base_queue_first: Option>> = None; // 更新后的baseQueue最后一个节点 let mut new_base_queue_last: Option>> = None; + let mut new_state = base_state.clone(); loop { - let mut update = update_option.clone().unwrap(); + let mut update = pending.clone().unwrap(); let update_lane = update.borrow().lane.clone(); if !is_subset_of_lanes(render_lanes.clone(), update_lane.clone()) { // underpriority @@ -113,6 +122,12 @@ pub fn process_update_queue( update.borrow().action.clone().unwrap(), update_lane.clone(), ))); + + if on_skip_update.is_some() { + let function = on_skip_update.unwrap(); + function(clone.clone()); + } + if new_base_queue_last.is_none() { new_base_queue_first = Some(clone.clone()); new_base_queue_last = Some(clone.clone()); @@ -120,7 +135,6 @@ pub fn process_update_queue( } else { new_base_queue_last.clone().unwrap().borrow_mut().next = Some(clone.clone()); } - result.skipped_update_lanes = merge_lanes(result.skipped_update_lanes, update_lane); } else { if new_base_queue_last.is_some() { let clone = Rc::new(RefCell::new(create_update( @@ -131,38 +145,86 @@ pub fn process_update_queue( new_base_queue_last = Some(clone.clone()) } - result.memoized_state = match update.borrow().action.clone() { - None => None, - Some(action) => { - let f = action.dyn_ref::(); - match f { - None => Some(MemoizedState::MemoizedJsValue(action.clone())), - Some(f) => match result.memoized_state.as_ref() { - Some(memoized_state) => { - if let MemoizedState::MemoizedJsValue(base_state) = - memoized_state - { - Some(MemoizedState::MemoizedJsValue( - f.call1(&JsValue::null(), base_state).unwrap(), - )) - } else { - log!("process_update_queue, base_state is not JsValue"); - None + if update.borrow().has_eager_state { + new_state = Some(MemoizedState::MemoizedJsValue( + update.borrow().eager_state.clone().unwrap(), + )); + } else { + // let b = match base_state.clone() { + // Some(s) => match s { + // MemoizedState::MemoizedJsValue(js_value) => Some(js_value), + // _ => None, + // }, + // None => None, + // }; + // new_state = if b.is_none() { + // None + // } else { + // Some(MemoizedState::MemoizedJsValue( + // basic_state_reducer( + // b.as_ref().unwrap(), + // &update.borrow().action.clone().unwrap(), + // ) + // .unwrap(), + // )) + // }; + new_state = match update.borrow().action.clone() { + None => None, + Some(action) => { + let f = action.dyn_ref::(); + match f { + None => Some(MemoizedState::MemoizedJsValue(action.clone())), + Some(f) => match result.memoized_state.as_ref() { + Some(memoized_state) => { + if let MemoizedState::MemoizedJsValue(base_state) = + memoized_state + { + Some(MemoizedState::MemoizedJsValue( + f.call1(&JsValue::null(), base_state).unwrap(), + )) + } else { + log!("process_update_queue, base_state is not JsValue"); + None + } } - } - None => Some(MemoizedState::MemoizedJsValue( - f.call1(&JsValue::null(), &JsValue::undefined()).unwrap(), - )), - }, + None => Some(MemoizedState::MemoizedJsValue( + f.call1(&JsValue::null(), &JsValue::undefined()).unwrap(), + )), + }, + } } - } - }; + }; + } + + // result.memoized_state = match update.borrow().action.clone() { + // None => None, + // Some(action) => { + // let f = action.dyn_ref::(); + // match f { + // None => Some(MemoizedState::MemoizedJsValue(action.clone())), + // Some(f) => match result.memoized_state.as_ref() { + // Some(memoized_state) => { + // if let MemoizedState::MemoizedJsValue(base_state) = + // memoized_state + // { + // Some(MemoizedState::MemoizedJsValue( + // f.call1(&JsValue::null(), base_state).unwrap(), + // )) + // } else { + // log!("process_update_queue, base_state is not JsValue"); + // None + // } + // } + // None => Some(MemoizedState::MemoizedJsValue( + // f.call1(&JsValue::null(), &JsValue::undefined()).unwrap(), + // )), + // }, + // } + // } + // }; } - update_option = update.clone().borrow().next.clone(); - if Rc::ptr_eq( - &update_option.clone().unwrap(), - &pending_update.clone().unwrap(), - ) { + pending = update.clone().borrow().next.clone(); + if Rc::ptr_eq(&pending.clone().unwrap(), &first.clone().unwrap()) { break; } } @@ -173,6 +235,7 @@ pub fn process_update_queue( new_base_queue_last.clone().unwrap().borrow_mut().next = new_base_queue_last.clone(); } + result.memoized_state = new_state; result.base_state = new_base_state; result.base_queue = new_base_queue_last.clone(); } From 5420eeeeeab2ed4a58c4811bafd87685f3b3626f Mon Sep 17 00:00:00 2001 From: youxingzhi Date: Mon, 22 Jul 2024 11:11:16 +0800 Subject: [PATCH 6/7] fix eagerState bug --- packages/react-reconciler/src/fiber_hooks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/fiber_hooks.rs b/packages/react-reconciler/src/fiber_hooks.rs index 4dc5a2c..ad46d63 100644 --- a/packages/react-reconciler/src/fiber_hooks.rs +++ b/packages/react-reconciler/src/fiber_hooks.rs @@ -488,7 +488,7 @@ fn dispatch_set_state( update.has_eager_state = true; update.eager_state = Some(eager_state.clone()); if Object::is(¤t_state, &eager_state) { - enqueue_update(update_queue.clone(), update, fiber.clone(), lane.clone()); + enqueue_update(update_queue.clone(), update, fiber.clone(), Lane::NoLane); if is_dev() { log!("Hit eager state") } From 8604acc233cb7090c90e6db88a5bce1af44f8a20 Mon Sep 17 00:00:00 2001 From: youxingzhi Date: Mon, 22 Jul 2024 14:05:23 +0800 Subject: [PATCH 7/7] opt eager state --- packages/react-reconciler/src/begin_work.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/react-reconciler/src/begin_work.rs b/packages/react-reconciler/src/begin_work.rs index 82a2a8e..d2ecadb 100644 --- a/packages/react-reconciler/src/begin_work.rs +++ b/packages/react-reconciler/src/begin_work.rs @@ -59,10 +59,10 @@ pub fn begin_work( unsafe { DID_RECEIVE_UPDATE = false; }; - let current = work_in_progress.borrow().alternate.clone(); + let current = { work_in_progress.borrow().alternate.clone() }; if current.is_some() { - let current = current.unwrap(); + let current = current.clone().unwrap(); let old_props = current.borrow().memoized_props.clone(); let old_type = current.borrow()._type.clone(); let new_props = work_in_progress.borrow().pending_props.clone(); @@ -95,6 +95,10 @@ pub fn begin_work( } work_in_progress.borrow_mut().lanes = Lane::NoLane; + // if current.is_some() { + // let current = current.clone().unwrap(); + // current.borrow_mut().lanes = Lane::NoLane; + // } let tag = work_in_progress.clone().borrow().tag.clone(); return match tag {