123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894type'valueref={mutablecurrent:'value}typedomRef=CallbackDomRefof(Dom.elementJs.nullable->unit)|CurrentDomRefofDom.elementJs.nullablerefmoduleRef=structtypet=domReftypecurrentDomRef=Dom.elementJs.nullablereftypecallbackDomRef=Dom.elementJs.nullable->unitletdomRef(v:currentDomRef)=CurrentDomRefvletcallbackDomRef(v:callbackDomRef)=CallbackDomRefvendletcreateRef()={current=None}letuseRefvalue={current=value}letforwardReff=f()moduleEvent=structtype'asynthetictypetarget_like=<checked:bool;className:string;id:string;innerHTML:string;name:string;tagName:string;textContent:string;value:string>letfailname=Runtime.fail_impossible_action_in_ssr("React.Event."^name)moduleMakeEventWithType(Type:sigtypetend)=structletbubbles:Type.t->bool=fun_->fail"bubbles"letcancelable:Type.t->bool=fun_->fail"cancelable"letcurrentTarget:Type.t->target_like=fun_->fail"currentTarget"letdefaultPrevented:Type.t->bool=fun_->fail"defaultPrevented"leteventPhase:Type.t->int=fun_->fail"eventPhase"letisTrusted:Type.t->bool=fun_->fail"isTrusted"letnativeEvent:Type.t->target_like=fun_->fail"nativeEvent"letpreventDefault:Type.t->unit=fun_->fail"preventDefault"letisDefaultPrevented:Type.t->bool=fun_->fail"isDefaultPrevented"letstopPropagation:Type.t->unit=fun_->fail"stopPropagation"letisPropagationStopped:Type.t->bool=fun_->fail"isPropagationStopped"lettarget:Type.t->target_like=fun_->fail"target"lettimeStamp:Type.t->float=fun_->fail"timeStamp"lettype_:Type.t->string=fun_->fail"type_"letpersist:Type.t->unit=fun_->fail"persist"endmoduleSynthetic=structtypetagtypet=tagsyntheticletbubbles:'asynthetic->bool=fun_->fail"Synthetic.bubbles"letcancelable:'asynthetic->bool=fun_->fail"Synthetic.cancelable"letcurrentTarget:'asynthetic->target_like=fun_->fail"Synthetic.currentTarget"letdefaultPrevented:'asynthetic->bool=fun_->fail"Synthetic.defaultPrevented"leteventPhase:'asynthetic->int=fun_->fail"Synthetic.eventPhase"letisTrusted:'asynthetic->bool=fun_->fail"Synthetic.isTrusted"letnativeEvent:'asynthetic->target_like=fun_->fail"Synthetic.nativeEvent"letpreventDefault:'asynthetic->unit=fun_->fail"Synthetic.preventDefault"letisDefaultPrevented:'asynthetic->bool=fun_->fail"Synthetic.isDefaultPrevented"letstopPropagation:'asynthetic->unit=fun_->fail"Synthetic.stopPropagation"letisPropagationStopped:'asynthetic->bool=fun_->fail"Synthetic.isPropagationStopped"lettarget:'asynthetic->target_like=fun_->fail"Synthetic.target"lettimeStamp:'asynthetic->float=fun_->fail"Synthetic.timeStamp"lettype_:'asynthetic->string=fun_->fail"Synthetic.type_"letpersist:'asynthetic->unit=fun_->fail"Synthetic.persist"end(* let toSyntheticEvent : 'a synthetic -> Synthetic.t = i -> i *)moduleClipboard=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letclipboardData:t->target_like=fun_->fail"Clipboard.clipboardData"endmoduleComposition=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letdata:t->string=fun_->fail"Composition.data"endmoduleKeyboard=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letaltKey:t->bool=fun_->fail"Keyboard.altKey"letcharCode:t->int=fun_->fail"Keyboard.charCode"letctrlKey:t->bool=fun_->fail"Keyboard.ctrlKey"letgetModifierState:t->string->bool=fun__->fail"Keyboard.getModifierState"letkey:t->string=fun_->fail"Keyboard.key"letkeyCode:t->int=fun_->fail"Keyboard.keyCode"letlocale:t->string=fun_->fail"Keyboard.locale"letlocation:t->int=fun_->fail"Keyboard.location"letmetaKey:t->bool=fun_->fail"Keyboard.metaKey"letrepeat:t->bool=fun_->fail"Keyboard.repeat"letshiftKey:t->bool=fun_->fail"Keyboard.shiftKey"letwhich:t->int=fun_->fail"Keyboard.which"endmoduleFocus=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letrelatedTarget:t->target_likeoption=fun_->fail"Focus.relatedTarget"endmoduleForm=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)endmoduleMouse=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letaltKey:t->bool=fun_->fail"Mouse.altKey"letbutton:t->int=fun_->fail"Mouse.button"letbuttons:t->int=fun_->fail"Mouse.buttons"letclientX:t->int=fun_->fail"Mouse.clientX"letclientY:t->int=fun_->fail"Mouse.clientY"letctrlKey:t->bool=fun_->fail"Mouse.ctrlKey"letgetModifierState:t->string->bool=fun__->fail"Mouse.getModifierState"letmetaKey:t->bool=fun_->fail"Mouse.metaKey"letmovementX:t->int=fun_->fail"Mouse.movementX"letmovementY:t->int=fun_->fail"Mouse.movementY"letpageX:t->int=fun_->fail"Mouse.pageX"letpageY:t->int=fun_->fail"Mouse.pageY"letrelatedTarget:t->target_likeoption=fun_->fail"Mouse.relatedTarget"letscreenX:t->int=fun_->fail"Mouse.screenX"letscreenY:t->int=fun_->fail"Mouse.screenY"letshiftKey:t->bool=fun_->fail"Mouse.shiftKey"endmodulePointer=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letdetail:t->int=fun_->fail"Pointer.detail"(* let view : t -> Dom.window *)letscreenX:t->int=fun_->fail"Pointer.screenX"letscreenY:t->int=fun_->fail"Pointer.screenY"letclientX:t->int=fun_->fail"Pointer.clientX"letclientY:t->int=fun_->fail"Pointer.clientY"letpageX:t->int=fun_->fail"Pointer.pageX"letpageY:t->int=fun_->fail"Pointer.pageY"letmovementX:t->int=fun_->fail"Pointer.movementX"letmovementY:t->int=fun_->fail"Pointer.movementY"letctrlKey:t->bool=fun_->fail"Pointer.ctrlKey"letshiftKey:t->bool=fun_->fail"Pointer.shiftKey"letaltKey:t->bool=fun_->fail"Pointer.altKey"letmetaKey:t->bool=fun_->fail"Pointer.metaKey"letgetModifierState:t->string->bool=fun__->fail"Pointer.getModifierState"letbutton:t->int=fun_->fail"Pointer.button"letbuttons:t->int=fun_->fail"Pointer.buttons"letrelatedTarget:t->target_likeoption=fun_->fail"Pointer.relatedTarget"(* let pointerId : t -> Dom.eventPointerId *)letwidth:t->float=fun_->fail"Pointer.width"letheight:t->float=fun_->fail"Pointer.height"letpressure:t->float=fun_->fail"Pointer.pressure"lettangentialPressure:t->float=fun_->fail"Pointer.tangentialPressure"lettiltX:t->int=fun_->fail"Pointer.tiltX"lettiltY:t->int=fun_->fail"Pointer.tiltY"lettwist:t->int=fun_->fail"Pointer.twist"letpointerType:t->string=fun_->fail"Pointer.pointerType"letisPrimary:t->bool=fun_->fail"Pointer.isPrimary"endmoduleSelection=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)endmoduleTouch=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letaltKey:t->bool=fun_->fail"Touch.altKey"letchangedTouches:t->target_like=fun_->fail"Touch.changedTouches"letctrlKey:t->bool=fun_->fail"Touch.ctrlKey"letgetModifierState:t->string->bool=fun__->fail"Touch.getModifierState"letmetaKey:t->bool=fun_->fail"Touch.metaKey"letshiftKey:t->bool=fun_->fail"Touch.shiftKey"lettargetTouches:t->target_like=fun_->fail"Touch.targetTouches"lettouches:t->target_like=fun_->fail"Touch.touches"endmoduleUI=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letdetail:t->int=fun_->fail"UI.detail"(* let view : t -> Dom.window *)endmoduleWheel=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letdeltaMode:t->int=fun_->fail"Wheel.deltaMode"letdeltaX:t->float=fun_->fail"Wheel.deltaX"letdeltaY:t->float=fun_->fail"Wheel.deltaY"letdeltaZ:t->float=fun_->fail"Wheel.deltaZ"endmoduleMedia=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)endmoduleImage=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)endmoduleAnimation=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letanimationName:t->string=fun_->fail"Animation.animationName"letpseudoElement:t->string=fun_->fail"Animation.pseudoElement"letelapsedTime:t->float=fun_->fail"Animation.elapsedTime"endmoduleTransition=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letpropertyName:t->string=fun_->fail"Transition.propertyName"letpseudoElement:t->string=fun_->fail"Transition.pseudoElement"letelapsedTime:t->float=fun_->fail"Transition.elapsedTime"endmoduleDrag=structtypetagtypet=tagsyntheticincludeMakeEventWithType(structtypenonrect=t[@@nonrec]end)letaltKey:t->bool=fun_->fail"Drag.altKey"letbutton:t->int=fun_->fail"Drag.button"letbuttons:t->int=fun_->fail"Drag.buttons"letclientX:t->int=fun_->fail"Drag.clientX"letclientY:t->int=fun_->fail"Drag.clientY"letctrlKey:t->bool=fun_->fail"Drag.ctrlKey"letgetModifierState:t->string->bool=fun__->fail"Drag.getModifierState"letmetaKey:t->bool=fun_->fail"Drag.metaKey"letmovementX:t->int=fun_->fail"Drag.movementX"letmovementY:t->int=fun_->fail"Drag.movementY"letpageX:t->int=fun_->fail"Drag.pageX"letpageY:t->int=fun_->fail"Drag.pageY"letrelatedTarget:t->target_likeoption=fun_->fail"Drag.relatedTarget"letscreenX:t->int=fun_->fail"Drag.screenX"letscreenY:t->int=fun_->fail"Drag.screenY"letshiftKey:t->bool=fun_->fail"Drag.shiftKey"letdataTransfer:t->target_like=fun_->fail"Drag.dataTransfer"endendmoduleJSX=structtypeevent=|Dragof(Event.Drag.t->unit)|Mouseof(Event.Mouse.t->unit)|Selectionof(Event.Selection.t->unit)|Touchof(Event.Touch.t->unit)|UIof(Event.UI.t->unit)|Wheelof(Event.Wheel.t->unit)|Clipboardof(Event.Clipboard.t->unit)|Compositionof(Event.Composition.t->unit)|Transitionof(Event.Transition.t->unit)|Animationof(Event.Animation.t->unit)|Pointerof(Event.Pointer.t->unit)|Keyboardof(Event.Keyboard.t->unit)|Focusof(Event.Focus.t->unit)|Formof(Event.Form.t->unit)|Mediaof(Event.Media.t->unit)|Inlineofstringtypeprop=|Action:(string*string*_Runtime.server_function)->prop|Boolof(string*string*bool)|BooleanishStringof(string*string*bool)|Stringof(string*string*string)|Intof(string*string*int)|Floatof(string*string*float)|Styleof(string*string*string)list|DangerouslyInnerHtmlofstring|RefofRef.t|Eventofstring*eventletboolnamejsxNamevalue=Bool(name,jsxName,value)letbooleanishStringnamejsxNamevalue=BooleanishString(name,jsxName,value)letstringnamejsxNamevalue=String(name,jsxName,value)letstylevalue=StylevalueletintnamejsxNamevalue=Int(name,jsxName,value)letfloatnamejsxNamevalue=Float(name,jsxName,value)letdangerouslyInnerHtmlvalue=DangerouslyInnerHtmlvalue#__htmlletrefvalue=Refvalueleteventkeyvalue=Event(key,value)moduleEvent=structletdragkeyvalue=eventkey(Dragvalue)letmousekeyvalue=eventkey(Mousevalue)letselectionkeyvalue=eventkey(Selectionvalue)lettouchkeyvalue=eventkey(Touchvalue)letuikeyvalue=eventkey(UIvalue)letwheelkeyvalue=eventkey(Wheelvalue)letclipboardkeyvalue=eventkey(Clipboardvalue)letcompositionkeyvalue=eventkey(Compositionvalue)lettransitionkeyvalue=eventkey(Transitionvalue)letanimationkeyvalue=eventkey(Animationvalue)letpointerkeyvalue=eventkey(Pointervalue)letkeyboardkeyvalue=eventkey(Keyboardvalue)letfocuskeyvalue=eventkey(Focusvalue)letformkeyvalue=eventkey(Formvalue)letmediakeyvalue=eventkey(Mediavalue)endendtypeerror={message:string;stack:Yojson.Basic.t;env:string;digest:string}moduleModel=structtype'elementt=|Function:'server_functionRuntime.server_function->'elementt|List:'elementtlist->'elementt|Assoc:(string*'elementt)list->'elementt|Json:Yojson.Basic.t->'elementt|Error:error->'elementt|Element:'element->'elementt|Promise:'aJs.Promise.t*('a->'elementt)->'elementtendtype('props,'return)componentLike=?key:string->'props->'returnandelement=|Lower_case_elementoflower_case_element|Upper_case_componentofstring*(unit->element)|Async_componentofstring*(unit->elementLwt.t)|Client_componentof{key:stringoption;props:client_props;client:element;import_module:string;import_name:string;}|Listofelementlist|Arrayofelementarray|Textofstring|Intofint|Floatoffloat|Staticof{prerendered:string;original:element}|Writerof{emit:Buffer.t->separators:bool->unit;original:unit->element}(** Like [Static] but writes directly into the caller's buffer. Used by the PPX for subtrees with static skeleton
\+ dynamic string/int/float holes (the [Needs_string_concat] and [Needs_buffer] tiers).
[separators] tells the emit function whether adjacent text nodes must be delimited with an [<!-- -->] comment,
matching react-dom: [renderToString] needs the delimiters so hydration can split merged text nodes,
[renderToStaticMarkup] must not emit them.
[original] is a thunk that rebuilds the variant-tree form on-demand for [cloneElement] and RSC consumers. Same
name as [Static.original] for symmetry; [Writer]'s version is lazy so the render-to-string fast path pays no
allocation for the fallback. *)|Fragmentofelement|Empty|Providerof{children:element;push:unit->unit->unit;async_key:Obj.tLwt.key;async_value:Obj.t}|Consumerofelement|Suspenseof{key:stringoption;children:element;fallback:elementoption}andlower_case_element={key:stringoption;tag:string;attributes:JSX.proplist;children:elementlist}andclient_props=(string*elementModel.t)listandmodel_value=elementModel.texceptionInvalid_childrenofstringletprop_key(prop:JSX.prop)=matchpropwith|Bool(name,_,_)->name|BooleanishString(name,_,_)->name|String(name,_,_)->name|Int(name,_,_)->name|Float(name,_,_)->name|Action(name,_,_)->name|Style_->"style"|DangerouslyInnerHtml_->"dangerouslySetInnerHTML"|Ref_->"ref"|Event(name,_)->name(* Merges attributes following JS object-spread semantics ([{...attributes, ...new_attributes}]): base attributes keep
their original order and are replaced in place when a new attribute shares their key; new attributes with unseen
keys are appended in their original order. If the same key appears multiple times in [new_attributes], the last
occurrence wins. O(n²) over List, which is fine: attribute lists are small and [cloneElement] is rare. *)letclone_attributes(attributes:JSX.proplist)(new_attributes:JSX.proplist)=letkey_equalskeyprop=String.equal(prop_keyprop)keyinletlast_new_with_keykey=List.fold_left(funaccprop->ifkey_equalskeypropthenSomepropelseacc)Nonenew_attributesinletbase=List.map(funattr->matchlast_new_with_key(prop_keyattr)withSomereplacement->replacement|None->attr)attributesinletrecappend_newseenprops=matchpropswith|[]->[]|prop::rest->letkey=prop_keypropinifList.exists(key_equalskey)attributes||List.memkeyseenthenappend_newseenrestelseletwinner=matchlast_new_with_keykeywithSomelast->last|None->propinwinner::append_new(key::seen)restinbase@append_new[]new_attributesletcreate_element_with_key?keytagattributeschildren=matchHtml.is_self_closing_tagtagwith|truewhenList.lengthchildren>0->raise(Invalid_children(Printf.sprintf{|"%s" is a self-closing tag and must not have "children".\n|}tag))|truewhenList.exists(functionJSX.DangerouslyInnerHtml_->true|_->false)attributes->raise(Invalid_children(Printf.sprintf{|"%s" is a self-closing tag and must not have "dangerouslySetInnerHTML".\n|}tag))|true->Lower_case_element{key;tag;attributes;children=[]}|false->Lower_case_element{key;tag;attributes;children}letcreateElement=create_element_with_key?key:NoneletcreateElementWithKey=create_element_with_keyletclone_component_errorname=Printf.sprintf"React.cloneElement: cannot clone '%s'. In server-reason-react, component props are compile-time labelled \
arguments (and extending them with new props at runtime is not supported). React.cloneElement only works with \
lowercase DOM elements."nameletreccloneElementelementnew_attributes=matchelementwith|Lower_case_element{key;tag;attributes;children}->Lower_case_element{key;tag;attributes=clone_attributesattributesnew_attributes;children}|Upper_case_component(name,_)->raise(Invalid_argument(clone_component_errorname))|Async_component(name,_)->raise(Invalid_argument(clone_component_errorname))|Client_component{import_name;_}->raise(Invalid_argument(clone_component_errorimport_name))|Static{original;prerendered=_}->cloneElementoriginalnew_attributes|Writer{original;emit=_}->cloneElement(original())new_attributes|Fragment_->raise(Invalid_argument"React.cloneElement: cannot clone a Fragment")|Text_|Int_|Float_->raise(Invalid_argument"React.cloneElement: cannot clone a Text element")|Empty->raise(Invalid_argument"React.cloneElement: cannot clone a null element")|List_->raise(Invalid_argument"React.cloneElement: cannot clone a List")|Array_->raise(Invalid_argument"React.cloneElement: cannot clone an Array")|Provider_->raise(Invalid_argument"React.cloneElement: cannot clone a Provider")|Consumer_->raise(Invalid_argument"React.cloneElement: cannot clone a Consumer")|Suspense_->raise(Invalid_argument"React.cloneElement: cannot clone a Suspense")moduleFragment=structletmakeProps~children():<children:element>Js.t=objectmethodchildren=childrenendletmake?key:_props=Fragmentprops#childrenendletfragmentchildren=Fragment.make(Fragment.makeProps~children())(* ReasonReact APIs *)letstringtxt=Texttxtletnull=Emptyletinti=Intiletfloatf=Floatfletarrayarr=Arrayarrletlistl=Listltype'aprovider=value:'a->children:element->unit->elementmoduleContext=structtype'at={current_value:'aref;async_key:Obj.tLwt.key;provider:'aprovider;consumer:children:element->element;}letmakeProps~value~children():<value:'a;children:element>Js.t=objectmethodvalue=valuemethodchildren=childrenendletproviderctx?key:_props=ctx.provider~value:props#value~children:props#children()endletcreateContext(initial_value:'a):'aContext.t=letref_value={current=initial_value}inletasync_key=Lwt.new_key()inletprovider~value~children()=Provider{children;push=(fun()->letprev=ref_value.currentinref_value.current<-value;fun()->ref_value.current<-prev);async_key;async_value=Obj.reprvalue;}inletconsumer~children=Consumerchildrenin{current_value=ref_value;async_key;provider;consumer}moduleSuspense=structletor_react_null=functionNone->null|Somex->xletmakeProps?fallback?children():<fallback:elementoption;children:elementoption>Js.t=objectmethodfallback=fallbackmethodchildren=childrenendletmake?keyprops=Suspense{key;fallback=props#fallback;children=or_react_nullprops#children}endmoduleCache=structtypecache_entry=OkofObj.t|Errorofexntypefn_cache=(Obj.t,cache_entry)Hashtbl.ttyperequest_cache=(int,fn_cache)Hashtbl.tletasync_key:request_cacheLwt.key=Lwt.new_key()letfn_id_counter:intStdlib.ref=Stdlib.ref0letwith_request_cachef=letcache=Hashtbl.create16inLwt.with_valueasync_key(Somecache)fletwith_request_cache_asyncf=letcache=Hashtbl.create16inLwt.with_valueasync_key(Somecache)fend(* On the server there's no re-render, so memoization is a no-op and the
component is passed through unchanged. Signatures match reason-react. *)letmemocomponent=componentletmemoCustomComparePropscomponent_compare=componentletcachefn=letfn_id=!Cache.fn_id_counterinCache.fn_id_counter:=fn_id+1;funarg->matchLwt.getCache.async_keywith|None->fnarg|Somecache_map->(letfn_cache=matchHashtbl.find_optcache_mapfn_idwith|Somecache->cache|None->letcache=Hashtbl.create8inHashtbl.addcache_mapfn_idcache;cacheinletarg_key=Obj.reprarginmatchHashtbl.find_optfn_cachearg_keywith|Some(Cache.Okvalue)->Obj.objvalue|Some(Cache.Errorerror)->raiseerror|None->(tryletresult=fnarginHashtbl.addfn_cachearg_key(Cache.Ok(Obj.reprresult));resultwithexn->Hashtbl.addfn_cachearg_key(Cache.Errorexn);raiseexn))letuseContext(context:'aContext.t)=matchLwt.getcontext.async_keywithSomev->(Obj.objv:'a)|None->context.current_value.currentletuseState(make_initial_value:unit->'state)=letinitial_value:'state=make_initial_value()inletsetState(fn:'state->'state)=let_=fninitial_valuein()in(initial_value,setState)type('input,'output)callback='input->'outputletuseSyncExternalStore~subscribe:_~getSnapshot=getSnapshot()letuseSyncExternalStoreWithServer~subscribe:_~getSnapshot:_~getServerSnapshot=getServerSnapshot()(* Tree context for useId — implements the same bit-packing algorithm as React's
ReactFizzTree_context.js to produce hydration-compatible IDs.
IDs are base-32 strings whose binary representation corresponds to the
position of a node in a tree. Every time the tree forks into multiple
children, additional bits encode the position of the child within the
current level of children. *)moduleTree_context=structtypet={id:int;overflow:string}letempty={id=1;overflow=""}(* Count leading zeros in a 32-bit representation.
Uses the same algorithm as Math.clz32 in JavaScript. *)letclz32x=ifx=0then32elseletn=Stdlib.ref0inletv=Stdlib.refxinif!vland0xFFFF0000=0then(n:=!n+16;v:=!vlsl16);if!vland0xFF000000=0then(n:=!n+8;v:=!vlsl8);if!vland0xF0000000=0then(n:=!n+4;v:=!vlsl4);if!vland0xC0000000=0then(n:=!n+2;v:=!vlsl2);if!vland0x80000000=0thenn:=!n+1;!nletget_bit_lengthn=32-clz32nletget_leading_bitid=1lsl(get_bit_lengthid-1)(* Convert a non-negative integer to a base-32 string (digits: 0-9, a-v).
Matches JavaScript's Number.prototype.toString(32). *)letint_to_base32n=ifn=0then"0"elseletdigits="0123456789abcdefghijklmnopqrstuv"inletbuf=Buffer.create8inletrecgon=ifn>0thenbegingo(n/32);Buffer.add_charbuf(String.getdigits(nmod32))endingon;Buffer.contentsbufletget_tree_idctx=letoverflow=ctx.overflowinletid_with_leading_bit=ctx.idinletid=id_with_leading_bitlandlnot(get_leading_bitid_with_leading_bit)inint_to_base32id^overflowletpushbase_ctx~total_children~index=letbase_id_with_leading_bit=base_ctx.idinletbase_overflow=base_ctx.overflowinletbase_length=get_bit_lengthbase_id_with_leading_bit-1inletbase_id=base_id_with_leading_bitlandlnot(1lslbase_length)inletslot=index+1inletlength=get_bit_lengthtotal_children+base_lengthiniflength>30thenbegin(* Overflow: convert some bits to base-32 string *)letnumber_of_overflow_bits=base_length-(base_lengthmod5)inletnew_overflow_bits=(1lslnumber_of_overflow_bits)-1inletnew_overflow=int_to_base32(base_idlandnew_overflow_bits)inletrest_of_base_id=base_idasrnumber_of_overflow_bitsinletrest_of_base_length=base_length-number_of_overflow_bitsinletrest_of_length=get_bit_lengthtotal_children+rest_of_base_lengthinletrest_of_new_bits=slotlslrest_of_base_lengthinletid=rest_of_new_bitslorrest_of_base_idinletoverflow=new_overflow^base_overflowin{id=(1lslrest_of_length)lorid;overflow}endelse(* Normal path *)letnew_bits=slotlslbase_lengthinletid=new_bitslorbase_idin{id=(1lsllength)lorid;overflow=base_overflow}end(* Rendering hook context — mutable state set by the renderer (ReactDOM) and
read by hooks (useId). This mirrors React's currentlyRenderingTask pattern
in ReactFizzHooks.js.
This state is process-global: two async renders (renderToStream/render_html)
must not be in flight concurrently in one process, or their useId state
interleaves at Lwt yields and produces hydration mismatches.
TODO: scope per render (Lwt.key, as React.Cache/Context do, or thread through
the renderer) before enabling concurrent renders. *)letcurrent_tree_context:Tree_context.tStdlib.ref=Stdlib.refTree_context.emptyletlocal_id_counter:intStdlib.ref=Stdlib.ref0letdid_render_id_hook:boolStdlib.ref=Stdlib.reffalseletidentifier_prefix:stringoptionStdlib.ref=Stdlib.refNoneletreset_component_id_state(ctx:Tree_context.t)=current_tree_context:=ctx;local_id_counter:=0;did_render_id_hook:=falseletcheck_did_render_id_hook()=!did_render_id_hookletreset_id_rendering?prefix()=current_tree_context:=Tree_context.empty;local_id_counter:=0;did_render_id_hook:=false;identifier_prefix:=prefix(* React 19 uses \u00ab (LEFT-POINTING DOUBLE ANGLE QUOTATION MARK) and
\u00bb (RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK) as ID delimiters. *)letid_start="\xc2\xab"letid_end="\xc2\xbb"letuseId()=lettree_id=Tree_context.get_tree_id!current_tree_contextinletlocal_id=!local_id_counterinlocal_id_counter:=local_id+1;did_render_id_hook:=true;match(!identifier_prefix,local_id>0)with|None,false->Printf.sprintf"%sR%s%s"id_starttree_idid_end|None,true->Printf.sprintf"%sR%sH%s%s"id_starttree_id(Tree_context.int_to_base32local_id)id_end|Someprefix,false->Printf.sprintf"%s%sR%s%s"id_startprefixtree_idid_end|Someprefix,true->Printf.sprintf"%s%sR%sH%s%s"id_startprefixtree_id(Tree_context.int_to_base32local_id)id_endletuseMemofn=fn()letuseMemo0fn=fn()letuseMemo1fn_=fn()letuseMemo2fn_=fn()letuseMemo3fn_=fn()letuseMemo4fn_=fn()letuseMemo5fn_=fn()letuseMemo6fn_=fn()letuseCallbackfn=fnletuseCallback0fn=fnletuseCallback1fn_=fnletuseCallback2fn_=fnletuseCallback3fn_=fnletuseCallback4fn_=fnletuseCallback5fn_=fnletuseCallback6fn_=fnletuseReducer_s=(s,fun_->())letuseReducerWithMapState_smapper=(mappers,fun_->())letuseEffect_=()letuseEffect0_=()letuseEffect1__=()letuseEffect2__=()letuseEffect3__=()letuseEffect4__=()letuseEffect5__=()letuseEffect6__=()letuseLayoutEffect0_=()letuseLayoutEffect1__=()letuseLayoutEffect2__=()letuseLayoutEffect3__=()letuseLayoutEffect4__=()letuseLayoutEffect5__=()letuseLayoutEffect6__=()moduleChildren=structletmapelementfn=matchelementwith|Listchildren->List.mapfnchildren|>list|Arraychildren->Array.mapfnchildren|>array|_->fnelementletmapWithIndexelementfn=matchelementwith|Listchildren->List.mapi(funindexelement->fnelementindex)children|>list|Arraychildren->Array.mapi(funindexelement->fnelementindex)children|>array|_->fnelement0letforEachelementfn=matchelementwith|Listchildren->List.iterfnchildren|Arraychildren->Array.iterfnchildren|_->let_=fnelementin()letforEachWithIndexelementfn=matchelementwith|Listchildren->List.iteri(funindexelement->fnelementindex)children|Arraychildren->Array.iteri(funindexelement->fnelementindex)children|_->let_=fnelement0in()letcountelement=matchelementwith|Listchildren->List.lengthchildren|Arraychildren->Array.lengthchildren|Empty->0|_->1letonlyelement=matchelementwith|List(child::_)->child|List[]->raise(Invalid_argument"Expected at least one child")|Arraychildren->ifArray.lengthchildren>=1thenArray.getchildren0elseraise(Invalid_argument"Expected at least one child")|_->element(* TODO: silly way to convert children to array, but isn't necessary in most cases *)lettoArrayelement=[|element|]endletsetDisplayName__=()letuseTransition()=(false,fun(_cb:unit->unit)->())letuseDebugValue:'value->?format:('value->string)->unit=fun[@warning"-16"]_?format:_->()letuseDeferredValuevalue=value(* `exception Suspend of 'a Lwt`
exceptions can't have type params, this is called existential wrapper *)typeany_promise=Any_promise:'aLwt.t->any_promiseexceptionSuspendofany_promiseletsuspendpromise=raise(Suspend(Any_promisepromise))moduleExperimental=structletusePromisepromise=matchLwt.statepromisewith|Sleep->suspendpromise(* TODO: Fail should raise a FailedSupense and catch at renderTo*? *)|Faile->raisee|Returnv->vletuseActionState?permalink:__actionstate=(state,(),false)end