Skip to content

Commit

Permalink
improve traces in the tests
Browse files Browse the repository at this point in the history
  • Loading branch information
davesnx committed Jan 21, 2025
1 parent 7e21588 commit db96053
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 86 deletions.
94 changes: 15 additions & 79 deletions packages/reactDom/src/ReactDOM.ml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ let complete_boundary_script =
let replacement b s = Printf.sprintf "$RC('B:%i','S:%i')" b s

let inline_complete_boundary_script boundary_id suspense_id =
(* TODO: it's always correct to asume that the first suspense_id is 0? Maybe we can have 2 suspense parallely and it's not the case anymore? *)
(* TODO: it's correct to asume that the first suspense_id is 0? *)
if boundary_id = 0 && suspense_id = 0 then
Html.raw (Printf.sprintf "<script>%s%s</script>" complete_boundary_script (replacement boundary_id suspense_id))
else Html.raw (Printf.sprintf "<script>%s</script>" (replacement boundary_id suspense_id))
Expand Down Expand Up @@ -138,20 +138,6 @@ let render_suspense_fallback_error ~exn element =

let rec render_to_stream ~context_state element =
let rec render_element element =
Dream.log "Rendering element type: %s"
(match (element : React.element) with
| Empty -> "Empty"
| Client_component _ -> "Client_component"
| Provider _ -> "Provider"
| Consumer _ -> "Consumer"
| Fragment _ -> "Fragment"
| List _ -> "List"
| Upper_case_component _ -> "Upper_case_component"
| Lower_case_element _ -> "Lower_case_element"
| Text _ -> "Text"
| InnerHtml _ -> "InnerHtml"
| Async_component _ -> "Async_component"
| Suspense _ -> "Suspense");
match (element : React.element) with
| Empty -> Lwt.return Html.null
(* TODO: Check if this breaks in the client. Maybe should throw an error/exn? *)
Expand All @@ -162,20 +148,6 @@ let rec render_to_stream ~context_state element =
| List arr ->
let%lwt childrens = arr |> Array.to_list |> Lwt_list.map_p render_element in
Lwt.return (Html.list childrens)
| Upper_case_component component -> (
Dream.log "RENDER - Upper_case_component start";
try
Dream.log "RENDER - Upper_case_component try";
let element = component () in
Dream.log "RENDER - Upper_case_component got element";
render_element element
with
| React.Suspend _ as exn ->
Dream.log "RENDER - Upper_case_component caught suspension";
raise exn
| exn ->
Dream.log "RENDER - Upper_case_component caught other: %s" (Printexc.to_string exn);
raise exn)
| Lower_case_element { tag; attributes; _ } when Html.is_self_closing_tag tag ->
Lwt.return (Html.node tag (attributes_to_html attributes) [])
| Lower_case_element { key = _; tag; attributes; children } ->
Expand All @@ -184,89 +156,58 @@ let rec render_to_stream ~context_state element =
Lwt.return (Html.node tag html_attributes inner)
| Text text -> Lwt.return (Html.string text)
| InnerHtml text -> Lwt.return (Html.raw text)
| Upper_case_component component -> (
try
let element = component () in
render_element element
with exn -> raise_notrace exn)
| Async_component component -> (
Dream.log "Rendering element type: Async_component";
let promise = component () in
match Lwt.state promise with
| Lwt.Return element ->
Dream.log "Async_component already resolved";
render_element element
| Lwt.Fail exn ->
Dream.log "Async_component failed";
raise exn
| Lwt.Sleep ->
Dream.log "Async_component sleeping";
raise (React.Suspend (Any_promise promise)))
| Lwt.Return element -> render_element element
| Lwt.Fail exn -> raise_notrace exn
| Lwt.Sleep -> raise_notrace (React.Suspend (Any_promise promise)))
| Suspense { children; fallback; _ } -> (
try%lwt
let%lwt element = render_element children in
Lwt.return element
with
| React.Suspend (Any_promise promise) -> (
match Lwt.state promise with
| Lwt.Return _ ->
Dream.log "Promise already resolved, rendering immediately";
let%lwt _ = promise in
render_element children
| Lwt.Return _ -> render_element children
| Lwt.Fail exn ->
Dream.log "Promise failed";
let%lwt fallback_element = render_element fallback in
Lwt.return (render_suspense_fallback_error ~exn fallback_element)
| Lwt.Sleep ->
Dream.log "Promise pending, setting up streaming";
let%lwt fallback_element = render_element fallback in
let current_boundary_id = context_state.boundary_id in
let current_suspense_id = context_state.suspense_id in
context_state.boundary_id <- context_state.boundary_id + 1;
context_state.suspense_id <- context_state.suspense_id + 1;
Dream.log "About to increment waiting";
context_state.waiting <- context_state.waiting + 1;
Dream.log "Waiting count: %s" (string_of_int context_state.waiting);

Lwt.async (fun () ->
Dream.log "Started async resolution for boundary %d" current_boundary_id;
let%lwt _ = promise in
Dream.log "Promise resolved for boundary %d" current_boundary_id;
let%lwt resolved_html = render_with_resolved ~context_state children in
Dream.log "Children re-rendered in async";
context_state.waiting <- context_state.waiting - 1;
Dream.log "Waiting count after resolve: %d" context_state.waiting;
if not context_state.closed then (
Dream.log "Stream still open, pushing updates";
context_state.push (render_suspense_resolved_element ~id:current_suspense_id resolved_html);
context_state.push (inline_complete_boundary_script current_boundary_id current_suspense_id));
Dream.log "Updates pushed";
if context_state.waiting = 0 then (
context_state.closed <- true;
context_state.close ());
Dream.log "Async work complete";
Lwt.return_unit);
Dream.log "Returning fallback";
Lwt.return ());

Lwt.return (render_suspense_fallback ~boundary_id:current_boundary_id fallback_element))
| exn ->
Dream.log "Error in Suspense boundary: %s" (Printexc.to_string exn);
let%lwt fallback_element = render_element fallback in
Lwt.return (render_suspense_fallback_error ~exn fallback_element))
in

render_element element

and render_with_resolved ~context_state element =
Dream.log "RENDER - render_with_resolved start";
let rec render_element element =
Dream.log "Rendering element type: %s"
(match (element : React.element) with
| Empty -> "Empty"
| Client_component _ -> "Client_component"
| Provider _ -> "Provider"
| Consumer _ -> "Consumer"
| Fragment _ -> "Fragment"
| List _ -> "List"
| Upper_case_component _ -> "Upper_case_component"
| Lower_case_element _ -> "Lower_case_element"
| Text _ -> "Text"
| InnerHtml _ -> "InnerHtml"
| Async_component _ -> "Async_component"
| Suspense _ -> "Suspense");
match (element : React.element) with
| Empty -> Lwt.return Html.null
| Client_component _ -> Lwt.return Html.null
Expand All @@ -288,11 +229,10 @@ and render_with_resolved ~context_state element =
| Text text -> Lwt.return (Html.string text)
| InnerHtml text -> Lwt.return (Html.raw text)
| Async_component component -> (
Dream.log "RENDER - render_with_resolved Async_component";
let promise = component () in
match Lwt.state promise with
| Lwt.Return resolved -> render_element resolved
| Lwt.Fail exn -> raise exn
| Lwt.Fail exn -> raise_notrace exn
| Lwt.Sleep ->
let%lwt resolved = promise in
render_element resolved)
Expand All @@ -302,11 +242,7 @@ and render_with_resolved ~context_state element =

let renderToStream ?pipe:_ element =
let stream, push_to_stream, close = Push_stream.make () in
let push html =
Dream.log "PUSH";
Dream.log "%s" (Html.to_string html);
push_to_stream (Html.to_string html)
in
let push html = push_to_stream (Html.to_string html) in
let context_state = { push; close; closed = false; waiting = 0; boundary_id = 0; suspense_id = 0 } in
let abort () =
(* TODO: Needs to flush the remaining loading fallbacks as HTML, and React.js will try to render the rest on the client. *)
Expand Down
2 changes: 1 addition & 1 deletion packages/reactDom/src/dune
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
(wrapped false)
(public_name server-reason-react.reactDom)
(private_modules Push_stream)
(libraries react js html lwt yojson runtime dream)
(libraries react js html lwt yojson runtime)
(preprocess
(pps lwt_ppx)))
10 changes: 4 additions & 6 deletions packages/reactDom/test/test_renderToStream.ml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ let suspense_with_always_throwing () =
Printexc.record_backtrace false;
let app () = React.Suspense.make ~fallback:(React.string "Loading...") ~children:(always_throwing_component ()) () in
let%lwt stream, _abort = ReactDOM.renderToStream (React.Upper_case_component app) in
(* and we need to enable it back, I guess! *)
(* and we need to enable it back for the next test *)
Printexc.record_backtrace true;
assert_stream stream
[ "<!--$!--><template data-msg=\"Failure(&quot;always throwing&quot;)\n\"></template>Loading...<!--/$-->" ]
Expand Down Expand Up @@ -188,20 +188,18 @@ let suspense_with_nested_suspense_with_error () =
~children:
(deffered_component ~seconds:0.02
~children:
(React.Suspense.make ~fallback:(React.string "Fallback 2") ~children:(always_throwing_component ()) ())
(let _ = Printexc.record_backtrace false in
React.Suspense.make ~fallback:(React.string "Fallback 2") ~children:(always_throwing_component ()) ())
())
()
in
Printexc.record_backtrace true;
let%lwt stream, _abort = ReactDOM.renderToStream (React.Upper_case_component app) in
assert_stream stream
[
"<!--$?--><template id=\"B:0\"></template>Fallback 1<!--/$-->";
"<div hidden id=\"S:0\"><div>Sleep 0.02 seconds<!-- -->, <!--$!--><template data-msg=\"Failure(&quot;always \
throwing&quot;)\n\
Raised at Stdlib__String.rindex_rec in file &quot;string.ml&quot;, line 145, characters 16-31\n\
Called from Stdlib__String.rindex in file &quot;string.ml&quot; (inlined), line 149, characters 17-46\n\
Called from Dream__server__Log.reporter.report.(fun) in file &quot;src/server/log.ml&quot;, line 195, \
characters 26-50\n\
\"></template>Fallback 2<!--/$--></div></div>";
rsc_script "$RC('B:0','S:0')";
]
Expand Down

0 comments on commit db96053

Please sign in to comment.