diff --git a/__tests__/react-dom/ReactFunctionComponent-test.js b/__tests__/react-dom/ReactFunctionComponent-test.js
index 055f36c..70ae515 100644
--- a/__tests__/react-dom/ReactFunctionComponent-test.js
+++ b/__tests__/react-dom/ReactFunctionComponent-test.js
@@ -17,6 +17,12 @@ function FunctionComponent(props) {
return
{props.name}
;
}
+function sleep(ms) {
+ return new Promise((resolve) => {
+ setTimeout(resolve, ms)
+ })
+}
+
describe('ReactFunctionComponent', () => {
beforeEach(() => {
jest.resetModules();
@@ -25,10 +31,11 @@ describe('ReactFunctionComponent', () => {
ReactTestUtils = require('../utils/test-utils')
});
- it('should render stateless component', () => {
+ it('should render stateless component', async () => {
const el = document.createElement('div');
// console.log(FunctionComponent.toString())
ReactDOM.createRoot(el).render();
+ await sleep(10)
expect(el.textContent).toBe('A');
});
diff --git a/examples/hello-world/src/main.tsx b/examples/hello-world/src/main.tsx
index fd0b0ef..8f70611 100644
--- a/examples/hello-world/src/main.tsx
+++ b/examples/hello-world/src/main.tsx
@@ -1,5 +1,5 @@
import {createRoot} from 'react-dom'
-import App from "./App.tsx";
+import App from './App.tsx'
const root = createRoot(document.getElementById("root"))
root.render()
diff --git a/packages/react-dom/src/host_config.rs b/packages/react-dom/src/host_config.rs
index 1e15926..f7e898b 100644
--- a/packages/react-dom/src/host_config.rs
+++ b/packages/react-dom/src/host_config.rs
@@ -1,8 +1,11 @@
use std::any::Any;
+use std::cell::RefCell;
use std::rc::Rc;
+use js_sys::{Function, global, Promise};
use js_sys::JSON::stringify;
use wasm_bindgen::JsValue;
+use wasm_bindgen::prelude::*;
use web_sys::{Node, window};
use react_reconciler::HostConfig;
@@ -31,6 +34,20 @@ pub fn to_string(js_value: &JsValue) -> String {
})
}
+#[wasm_bindgen]
+extern "C" {
+ type Global;
+
+ #[wasm_bindgen]
+ fn queueMicrotask(closure: &JsValue);
+
+ #[wasm_bindgen]
+ fn setTimeout(closure: &JsValue, timeout: i32);
+
+ #[wasm_bindgen(method, getter, js_name = queueMicrotask)]
+ fn hasQueueMicrotask(this: &Global) -> JsValue;
+}
+
impl HostConfig for ReactDomHostConfig {
fn create_text_instance(&self, content: &JsValue) -> Rc {
let window = window().expect("no global `window` exists");
@@ -135,4 +152,35 @@ impl HostConfig for ReactDomHostConfig {
}
}
}
+
+ fn schedule_microtask(&self, callback: Box) {
+ let closure = Rc::new(RefCell::new(Some(Closure::wrap(callback))));
+
+ if global()
+ .unchecked_into::()
+ .hasQueueMicrotask()
+ .is_function()
+ {
+ let closure_clone = closure.clone();
+ queueMicrotask(&closure_clone.borrow_mut().as_ref().unwrap().as_ref().unchecked_ref::());
+ closure_clone.borrow_mut().take().unwrap_throw().forget();
+ } else if js_sys::Reflect::get(&*global(), &JsValue::from_str("Promise"))
+ .map(|value| value.is_function())
+ .unwrap_or(false)
+ {
+ let promise = Promise::resolve(&JsValue::NULL);
+ let closure_clone = closure.clone();
+ let c = Closure::wrap(Box::new(move |_v| {
+ let b = closure_clone.borrow_mut();
+ let function = b.as_ref().unwrap().as_ref().unchecked_ref::();
+ let _ = function.call0(&JsValue::NULL);
+ }) as Box);
+ let _ = promise.then(&c);
+ c.forget();
+ } else {
+ let closure_clone = closure.clone();
+ setTimeout(&closure_clone.borrow_mut().as_ref().unwrap().as_ref().unchecked_ref::(), 0);
+ closure_clone.borrow_mut().take().unwrap_throw().forget();
+ }
+ }
}
diff --git a/packages/react-reconciler/src/begin_work.rs b/packages/react-reconciler/src/begin_work.rs
index 6560b28..02863e3 100644
--- a/packages/react-reconciler/src/begin_work.rs
+++ b/packages/react-reconciler/src/begin_work.rs
@@ -8,16 +8,18 @@ use shared::derive_from_js_value;
use crate::child_fiber::{mount_child_fibers, reconcile_child_fibers};
use crate::fiber::{FiberNode, MemoizedState};
use crate::fiber_hooks::render_with_hooks;
+use crate::fiber_lanes::Lane;
use crate::update_queue::process_update_queue;
use crate::work_tags::WorkTag;
pub fn begin_work(
work_in_progress: Rc>,
+ render_lane: Lane,
) -> Result