local P local k local p local O local V local Q local s local x local J local U local b local a local G local I local o local D local i=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\106\101\115\116-\103\108\111\098\097\108\115")local W=i.expect local Y=i.jest local t=i.describe local e=i.beforeEach local L=i.it local h=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\112\114\111\109\105\115\101")local function R(i)local W=(function()if i.enableProfilerTimer~=nil then return i.enableProfilerTimer end return true end)()local Y=(function()if i.enableProfilerCommitHooks~=nil then return i.enableProfilerCommitHooks end return true end)()local t=(function()if i.enableSchedulerTracing~=nil then return i.enableSchedulerTracing end return true end)()local e=(function()if i.replayFailedUnitOfWorkWithInvokeGuardedCallback~=nil then return i.replayFailedUnitOfWorkWithInvokeGuardedCallback end return false end)()local L=(function()if i.useNoopRenderer~=nil then return i.useNoopRenderer end return false end)()k=(require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\115\104\097\114\101\100")).ReactFeatureFlags k.enableProfilerTimer=W k.enableProfilerCommitHooks=Y k.enableSchedulerTracing=t k.replayFailedUnitOfWorkWithInvokeGuardedCallback=e local R=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\108\117\097\117-\112\111\108\121\102\105\108\108")o=R.setTimeout D=R.Set P=require("\046\046\047\105\110\105\116")O=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\115\099\104\101\100\117\108\101\114")x=O.tracing V=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\114\101\097\099\116-\099\097\099\104\101")if L then p=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\114\101\097\099\116-\110\111\111\112-\114\101\110\100\101\114\101\114")Q=nil s=nil else p=nil Q=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\114\101\097\099\116-\116\101\115\116-\114\101\110\100\101\114\101\114")s=Q.unstable_concurrentAct end J=P.Component:extend("\065\100\118\097\110\099\101\084\105\109\101")J.defaultProps={byAmount=10;shouldComponentUpdate=true}function J.shouldComponentUpdate(k,P)return P.shouldComponentUpdate end function J.render(P)O.unstable_advanceTime(P.props.byAmount)return P.props.children or nil end I=nil G=V.unstable_createResource(function(P)local k,p=P[1],P[2]or 0 I=h.new(function(P,V)o(function()O.unstable_yieldValue(string.format("\080\114\111\109\105\115\101 \114\101\115\111\108\118\101\100 \091\037\115\093",tostring(k)))P(k)end,p)end)return I end,function(P)local k=P[1]return k end)U=function(P)local k,p=P.ms,P.text local V,Q=pcall(function()G.read({p;k})O.unstable_yieldValue(string.format("\065\115\121\110\099\084\101\120\116 \091\037\115\093",p))return p end)if not V then local P=Q if typeof(P.andThen)=="\102\117\110\099\116\105\111\110"then O.unstable_yieldValue(string.format("\083\117\115\112\101\110\100 \091\037\115\093",p))else O.unstable_yieldValue(string.format("\069\114\114\111\114 \091\037\115\093",p))end error(P)end end a=function(P)local k=P.text O.unstable_yieldValue(string.format("\084\101\120\116 \091\037\115\093",k))return k end b=function()P.useEffect(function() end)return nil end end t("\080\114\111\102\105\108\101\114",function()t("\119\111\114\107\115 \105\110 \112\114\111\102\105\108\105\110\103 \097\110\100 \110\111\110-\112\114\111\102\105\108\105\110\103 \098\117\110\100\108\101\115",function()for k,p in{true,false}do for k,O in{true,false}do t("\101\110\097\098\108\101\083\099\104\101\100\117\108\101\114\084\114\097\099\105\110\103\058"..((function()if p then return"\101\110\097\098\108\101\100"end return"\100\105\115\097\098\108\101\100"end)()..(" \101\110\097\098\108\101\080\114\111\102\105\108\101\114\084\105\109\101\114\058"..((function()if O then return"\101\110\097\098\108\101\100"end return"\100\105\115\097\098\108\101\100"end)().."\125"))),function()if _G.__DEV__ and O then e(function()Y.resetModules()R({enableSchedulerTracing=p,enableProfilerTimer=O,replayFailedUnitOfWorkWithInvokeGuardedCallback=false})end)end if _G.__DEV__ and O then L("\115\104\111\117\108\100 \119\097\114\110 \105\102 \114\101\113\117\105\114\101\100 \112\097\114\097\109\115 \097\114\101 \109\105\115\115\105\110\103",function()(W(function()Q.create(P.createElement(P.Profiler))end)).toErrorDev("\080\114\111\102\105\108\101\114 \109\117\115\116 \115\112\101\099\105\102\121 \097\110 \"\105\100\" \097\115 \097 \112\114\111\112",{withoutStack=true})end)L("\115\104\111\117\108\100 \115\117\112\112\111\114\116 \097\110 \101\109\112\116\121 \080\114\111\102\105\108\101\114 \040\119\105\116\104 \110\111 \099\104\105\108\100\114\101\110\041",function()(W(function()(Q.create(P.createElement(P.Profiler,{id="\108\097\098\101\108";onRender=Y.fn()}))):toJSON()end)).never.toThrow()end)L("\115\104\111\117\108\100 \114\101\110\100\101\114 \099\104\105\108\100\114\101\110",function()local k=function(k)local p=k.label return P.createElement("\115\112\097\110",nil,p)end local p=Q.create(P.createElement("\100\105\118",nil,P.createElement("\115\112\097\110",nil,"\111\117\116\115\105\100\101 \115\112\097\110"),P.createElement(P.Profiler,{id="\108\097\098\101\108";onRender=Y.fn()},P.createElement("\115\112\097\110",nil,"\105\110\115\105\100\101 \115\112\097\110"),P.createElement(k,{label="\102\117\110\099\116\105\111\110 \099\111\109\112\111\110\101\110\116"}))));(W(function()p:toJSON()end)).never.toThrow()end)L("\115\104\111\117\108\100 \115\117\112\112\111\114\116 \110\101\115\116\101\100 \080\114\111\102\105\108\101\114\115",function()local k=function(k)local p=k.label return P.createElement("\100\105\118",nil,p)end local p=P.Component:extend("\067\108\097\115\115\067\111\109\112\111\110\101\110\116")function p.render(k)return P.createElement("\098\108\111\099\107",nil,k.props.label)end local O=Q.create(P.createElement(P.Profiler,{id="\111\117\116\101\114";onRender=Y.fn()},P.createElement(k,{label="\111\117\116\101\114 \102\117\110\099\116\105\111\110 \099\111\109\112\111\110\101\110\116"}),P.createElement(P.Profiler,{id="\105\110\110\101\114",onRender=Y.fn()},P.createElement(p,{label="\105\110\110\101\114 \099\108\097\115\115 \099\111\109\112\111\110\101\110\116"}),P.createElement("\115\112\097\110",nil,"\105\110\110\101\114 \115\112\097\110"))));(W(function()O:toJSON()end)).never.toThrow()end)end end)end end end)for k,V in{true;false}do t("\111\110\082\101\110\100\101\114 \101\110\097\098\108\101\083\099\104\101\100\117\108\101\114\084\114\097\099\105\110\103\058"..(function()if V then return"\101\110\097\098\108\101\100"end return"\100\105\115\097\098\108\101\100"end)(),function()e(function()Y.resetModules()R({enableSchedulerTracing=V,replayFailedUnitOfWorkWithInvokeGuardedCallback=false})end)L("\115\104\111\117\108\100 \104\097\110\100\108\101 \101\114\114\111\114\115 \116\104\114\111\119\110",function()local k=Y.fn(function(P)if P=="\116\104\114\111\119"then error("\101\120\112\101\099\116\101\100")end end)local p=false local O=P.Component:extend("\067\108\097\115\115\067\111\109\112\111\110\101\110\116")function O.componentDidMount(P)p=true end function O.render(P)return P.props.children end;(W(function()Q.create(P.createElement(O,nil,P.createElement(P.Profiler,{id="\100\111-\110\111\116-\116\104\114\111\119";onRender=k},P.createElement(P.Profiler,{id="\116\104\114\111\119",onRender=k},P.createElement("\100\105\118")))))end)).toThrow("\101\120\112\101\099\116\101\100");(W(p)).toBe(true);(W(k)).toHaveBeenCalledTimes(2)end)L("\105\115 \110\111\116 \105\110\118\111\107\101\100 \117\110\116\105\108 \116\104\101 \099\111\109\109\105\116 \112\104\097\115\101",function()local k=Y.fn()local p=function(P)local k=P.value O.unstable_yieldValue(k)return nil end Q.create(P.createElement(P.Profiler,{id="\116\101\115\116",onRender=k},P.createElement(p,{value="\102\105\114\115\116"}),P.createElement(p,{value="\108\097\115\116"})),{unstable_isConcurrent=true});(W(O)).toFlushAndYieldThrough({"\102\105\114\115\116"});(W(k)).toHaveBeenCalledTimes(0);(W(O)).toFlushAndYield({"\108\097\115\116"});(W(k)).toHaveBeenCalledTimes(1)end)L("\100\111\101\115 \110\111\116 \114\101\112\111\114\116 \119\111\114\107 \100\111\110\101 \111\110 \097 \115\105\098\108\105\110\103",function()local k=Y.fn()local p=P.memo(function()O.unstable_advanceTime(10)return nil end,function()return true end)local x local function J()local k,p=P.useState(0)x=function()p(k+1)end return nil end local function U()return P.createElement(P.Fragment,nil,P.createElement(P.Profiler,{id="\116\101\115\116";onRender=k},P.createElement(p)),P.createElement(J))end local b=Q.create(P.createElement(U));(W(k)).toHaveBeenCalledTimes(1)local a=k.mock.calls[1];(W(a)).toHaveLength((function()if V then return 7 else return 6 end end)());(W(a[1])).toBe("\116\101\115\116");(W(a[2])).toBe("\109\111\117\110\116");(W(a[3])).toBe(10);(W(a[4])).toBe(10);(W(a[5])).toBe(0);(W(a[6])).toBe(10);(W(a[7])).toEqual((function()if V then return D.new()else return nil end end)())k:mockReset()O.unstable_advanceTime(20)b.update(P.createElement(U));(W(k)).never.toHaveBeenCalled()O.unstable_advanceTime(20)s(x);(W(k)).never.toHaveBeenCalled()end)L("\108\111\103\115 \114\101\110\100\101\114 \116\105\109\101\115 \102\111\114 \098\111\116\104 \109\111\117\110\116 \097\110\100 \117\112\100\097\116\101",function()local k=Y.fn()O.unstable_advanceTime(5)local p=Q.create(P.createElement(P.Profiler,{id="\116\101\115\116",onRender=k},P.createElement(J)));(W(k)).toHaveBeenCalledTimes(1)local s=k.mock.calls[1];(W(s)).toHaveLength((function()if V then return 7 else return 6 end end)());(W(s[1])).toBe("\116\101\115\116");(W(s[2])).toBe("\109\111\117\110\116");(W(s[3])).toBe(10);(W(s[4])).toBe(10);(W(s[5])).toBe(5);(W(s[6])).toBe(15);(W(s[7])).toEqual((function()if V then return D.new()else return nil end end)())k.mockReset()O.unstable_advanceTime(20)p.update(P.createElement(P.Profiler,{id="\116\101\115\116",onRender=k},P.createElement(J)));(W(k)).toHaveBeenCalledTimes(1)s=k.mock.calls[1];(W(s)).toHaveLength((function()if V then return 7 else return 6 end end)());(W(s[1])).toBe("\116\101\115\116");(W(s[2])).toBe("\117\112\100\097\116\101");(W(s[3])).toBe(10);(W(s[4])).toBe(10);(W(s[5])).toBe(35);(W(s[6])).toBe(45);(W(s[7])).toEqual((function()if V then return D.new()else return nil end end)())k.mockReset()O.unstable_advanceTime(20)p.update(P.createElement(P.Profiler,{id="\116\101\115\116",onRender=k},P.createElement(J,{byAmount=4})));(W(k)).toHaveBeenCalledTimes(1)s=k.mock.calls[1];(W(s)).toHaveLength((function()if V then return 7 else return 6 end end)());(W(s[1])).toBe("\116\101\115\116");(W(s[2])).toBe("\117\112\100\097\116\101");(W(s[3])).toBe(4);(W(s[4])).toBe(4);(W(s[5])).toBe(65);(W(s[6])).toBe(69);(W(s[7])).toEqual((function()if V then return D.new()else return nil end end)())end)L("\105\110\099\108\117\100\101\115 \114\101\110\100\101\114 \116\105\109\101\115 \111\102 \110\101\115\116\101\100 \080\114\111\102\105\108\101\114\115 \105\110 \116\104\101\105\114 \112\097\114\101\110\116 \116\105\109\101\115",function()local k=Y.fn()O.unstable_advanceTime(5)Q.create(P.createElement(P.Fragment,nil,P.createElement(P.Profiler,{id="\112\097\114\101\110\116",onRender=k},P.createElement(J,{byAmount=10},P.createElement(P.Profiler,{id="\099\104\105\108\100",onRender=k},P.createElement(J,{byAmount=20}))))));(W(k)).toHaveBeenCalledTimes(2)local p,V=k.mock.calls[1],k.mock.calls[2];(W(p[1])).toBe("\099\104\105\108\100");(W(V[1])).toBe("\112\097\114\101\110\116");(W(p[3])).toBe(20);(W(p[4])).toBe(20);(W(p[5])).toBe(15);(W(p[6])).toBe(35);(W(V[3])).toBe(30);(W(V[4])).toBe(30);(W(V[5])).toBe(5);(W(V[6])).toBe(35)end)L("\116\114\097\099\101\115 \115\105\098\108\105\110\103 \080\114\111\102\105\108\101\114\115 \115\101\112\097\114\097\116\101\108\121",function()local k=Y.fn()O.unstable_advanceTime(5)Q.create(P.createElement(P.Fragment,nil,P.createElement(P.Profiler,{id="\102\105\114\115\116";onRender=k},P.createElement(J,{byAmount=20})),P.createElement(P.Profiler,{id="\115\101\099\111\110\100",onRender=k},P.createElement(J,{byAmount=5}))));(W(k)).toHaveBeenCalledTimes(2)local p,V=k.mock.calls[1],k.mock.calls[2];(W(p[1])).toBe("\102\105\114\115\116");(W(V[1])).toBe("\115\101\099\111\110\100");(W(p[3])).toBe(20);(W(p[4])).toBe(20);(W(p[5])).toBe(5);(W(p[6])).toBe(30);(W(V[3])).toBe(5);(W(V[4])).toBe(5);(W(V[5])).toBe(25);(W(V[6])).toBe(30)end)L("\100\111\101\115 \110\111\116 \105\110\099\108\117\100\101 \116\105\109\101 \115\112\101\110\116 \111\117\116\115\105\100\101 \111\102 \112\114\111\102\105\108\101 \114\111\111\116",function()local k=Y.fn()O.unstable_advanceTime(5)Q.create(P.createElement(P.Fragment,nil,P.createElement(J,{byAmount=20}),P.createElement(P.Profiler,{id="\116\101\115\116",onRender=k},P.createElement(J,{byAmount=5})),P.createElement(J,{byAmount=20})));(W(k)).toHaveBeenCalledTimes(1)local p=k.mock.calls[1];(W(p[1])).toBe("\116\101\115\116");(W(p[3])).toBe(5);(W(p[4])).toBe(5);(W(p[5])).toBe(25);(W(p[6])).toBe(50)end)L("\105\115 \110\111\116 \099\097\108\108\101\100 \119\104\101\110 \098\108\111\099\107\101\100 \098\121 \115\067\085 \102\097\108\115\101",function()local k=Y.fn()local p local O=P.Component:extend("\085\112\100\097\116\101\114")function O.init(P)P.state={}end function O.render(P)p=P return P.props.children end local V=Q.create(P.createElement(P.Profiler,{id="\111\117\116\101\114",onRender=k},P.createElement(O,nil,P.createElement(P.Profiler,{id="\105\110\110\101\114",onRender=k},P.createElement("\100\105\118")))));(W(k)).toHaveBeenCalledTimes(2)k:mockReset()V.unstable_flushSync(function()p:setState({count=1})end);(W(k)).toHaveBeenCalledTimes(1);(W(k.mock.calls[1][1])).toBe("\111\117\116\101\114")end)L("\100\101\099\114\101\097\115\101\115 \097\099\116\117\097\108 \116\105\109\101 \098\117\116 \110\111\116 \098\097\115\101 \116\105\109\101 \119\104\101\110 \115\067\085 \112\114\101\118\101\110\116\115 \097\110 \117\112\100\097\116\101",function()local k=Y.fn()O.unstable_advanceTime(5)local p=Q.create(P.createElement(P.Profiler,{id="\116\101\115\116";onRender=k},P.createElement(J,{byAmount=10},P.createElement(J,{byAmount=13,shouldComponentUpdate=false}))));(W(k)).toHaveBeenCalledTimes(1)O.unstable_advanceTime(30)p.update(P.createElement(P.Profiler,{id="\116\101\115\116",onRender=k},P.createElement(J,{byAmount=4},P.createElement(J,{byAmount=7;shouldComponentUpdate=false}))));(W(k)).toHaveBeenCalledTimes(2)local V,s=k.mock.calls[1],k.mock.calls[2];(W(V[2])).toBe("\109\111\117\110\116");(W(V[3])).toBe(23);(W(V[4])).toBe(23);(W(V[5])).toBe(5);(W(V[6])).toBe(28);(W(s[2])).toBe("\117\112\100\097\116\101");(W(s[3])).toBe(4);(W(s[4])).toBe(17);(W(s[5])).toBe(58);(W(s[6])).toBe(62)end)L("\105\110\099\108\117\100\101\115 \116\105\109\101 \115\112\101\110\116 \105\110 \114\101\110\100\101\114 \112\104\097\115\101 \108\105\102\101\099\121\099\108\101\115",function()local k=P.Component:extend("\087\105\116\104\076\105\102\101\099\121\099\108\101\115")function k.init(P)P.state={}end k.getDerivedStateFromProps=function()O.unstable_advanceTime(3)return nil end function k.shouldComponentUpdate(P)O.unstable_advanceTime(7)return true end function k.render(P)O.unstable_advanceTime(5)return nil end local p=Y.fn()O.unstable_advanceTime(5)local V=Q.create(P.createElement(P.Profiler,{id="\116\101\115\116",onRender=p},P.createElement(k)))O.unstable_advanceTime(15)V.update(P.createElement(P.Profiler,{id="\116\101\115\116",onRender=p},P.createElement(k)));(W(p)).toHaveBeenCalledTimes(2)local s,x=p.mock.calls[1],p.mock.calls[2];(W(s[2])).toBe("\109\111\117\110\116");(W(s[3])).toBe(8);(W(s[4])).toBe(8);(W(s[5])).toBe(5);(W(s[6])).toBe(13);(W(x[2])).toBe("\117\112\100\097\116\101");(W(x[3])).toBe(15);(W(x[4])).toBe(15);(W(x[5])).toBe(28);(W(x[6])).toBe(43)end)t("\119\105\116\104 \114\101\103\097\114\100 \116\111 \105\110\116\101\114\114\117\112\116\105\111\110\115",function()for k,V in{true,false}do t("\114\101\112\108\097\121\070\097\105\108\101\100\085\110\105\116\079\102\087\111\114\107\087\105\116\104\073\110\118\111\107\101\071\117\097\114\100\101\100\067\097\108\108\098\097\099\107 "..(function()if V then return"\101\110\097\098\108\101\100"end return"\100\105\115\097\098\108\101\100"end)(),function()e(function()Y.resetModules()R({replayFailedUnitOfWorkWithInvokeGuardedCallback=V})end)L("\115\104\111\117\108\100 \097\099\099\117\109\117\108\097\116\101 \097\099\116\117\097\108 \116\105\109\101 \097\102\116\101\114 \097\110 \101\114\114\111\114 \104\097\110\100\108\101\100 \098\121 \099\111\109\112\111\110\101\110\116\068\105\100\067\097\116\099\104\040\041",function()local k=Y.fn()local p=function(P)local k=P.unused O.unstable_advanceTime(3)error("\101\120\112\101\099\116\101\100 \101\114\114\111\114")end local s=P.Component:extend("\069\114\114\111\114\066\111\117\110\100\097\114\121")function s.init(P)P.state={error_=nil}end function s.componentDidCatch(k,P)k:setState({error_=P})end function s.render(k)O.unstable_advanceTime(2)return(function()if k.state.error_==nil then return k.props.children end return P.createElement(J,{byAmount=20})end)()end O.unstable_advanceTime(5)Q.create(P.createElement(P.Profiler,{id="\116\101\115\116",onRender=k},P.createElement(s,nil,P.createElement(J,{byAmount=9}),P.createElement(p))));(W(k)).toHaveBeenCalledTimes(2)local x,U=k.mock.calls[1],k.mock.calls[2];(W(x[2])).toBe("\109\111\117\110\116");(W(x[3])).toBe(14);(W(x[4])).toBe(2);(W(x[5])).toBe(5);(W(x[6])).toBe((function()if _G.__DEV__ and V then return 22 end return 19 end)());(W(U[2])).toBe("\117\112\100\097\116\101");(W(U[3])).toBe(22);(W(U[4])).toBe(22);(W(U[5])).toBe((function()if _G.__DEV__ and V then return 22 end return 19 end)());(W(U[6])).toBe((function()if _G.__DEV__ and V then return 44 end return 41 end)())end)L("\115\104\111\117\108\100 \097\099\099\117\109\117\108\097\116\101 \097\099\116\117\097\108 \116\105\109\101 \097\102\116\101\114 \097\110 \101\114\114\111\114 \104\097\110\100\108\101\100 \098\121 \103\101\116\068\101\114\105\118\101\100\083\116\097\116\101\070\114\111\109\069\114\114\111\114\040\041",function()local k=Y.fn()local p=function(P)local k=P.unused O.unstable_advanceTime(10)error("\101\120\112\101\099\116\101\100 \101\114\114\111\114")end local s=P.Component:extend("\069\114\114\111\114\066\111\117\110\100\097\114\121")function s.init(P)P.state={error_=nil}end function s.getDerivedStateFromError(P)return{error_=P}end function s.render(k)O.unstable_advanceTime(2)return(function()if k.state.error_==nil then return k.props.children end return P.createElement(J,{byAmount=20})end)()end O.unstable_advanceTime(5)Q.create(P.createElement(P.Profiler,{id="\116\101\115\116";onRender=k},P.createElement(s,nil,P.createElement(J,{byAmount=5}),P.createElement(p))));(W(k)).toHaveBeenCalledTimes(1)local x=k.mock.calls[1];(W(x[2])).toBe("\109\111\117\110\116");(W(x[3])).toBe(39);(W(x[4])).toBe(22);(W(x[5])).toBe(5);(W(x[6])).toBe((function()if _G.__DEV__ and V then return 54 end return 44 end)())end)L("\115\104\111\117\108\100 \114\101\115\101\116 \116\104\101 \102\105\098\101\114 \115\116\097\099\107 \099\111\114\114\101\099\116 \097\102\116\101\114 \097 \"\099\111\109\112\108\101\116\101\" \112\104\097\115\101 \101\114\114\111\114",function()Y.resetModules()R({useNoopRenderer=true;replayFailedUnitOfWorkWithInvokeGuardedCallback=V})p.render(P.createElement(P.Profiler,{id="\112\114\111\102\105\108\101\114",onRender=Y.fn()},P.createElement("\101\114\114\111\114\073\110\067\111\109\112\108\101\116\101\080\104\097\115\101",nil,"\104\105")));(W(O)).toFlushAndThrow("\069\114\114\111\114 \105\110 \104\111\115\116 \099\111\110\102\105\103\046")p.render(P.createElement(P.Profiler,{id="\112\114\111\102\105\108\101\114";onRender=Y.fn()},P.createElement("\101\114\114\111\114\073\110\067\111\109\112\108\101\116\101\080\104\097\115\101",nil,P.createElement("\115\112\097\110",nil,"\104\105"))));(W(O)).toFlushAndThrow("\069\114\114\111\114 \105\110 \104\111\115\116 \099\111\110\102\105\103\046")p.render(P.createElement(P.Profiler,{id="\112\114\111\102\105\108\101\114";onRender=Y.fn()},P.createElement("\115\112\097\110",nil,"\104\105")));(W(O)).toFlushWithoutYielding()end)end)end end)end)end end)
-- ROBLOX upstream: https://github.com/facebook/react/blob/v17.0.1/packages/react/src/__tests__/ReactProfiler-test.internal.js
local React
local ReactFeatureFlags
local ReactNoop
local Scheduler
local ReactCache
local ReactTestRenderer
local ReactTestRendererAct
local _SchedulerTracing
local AdvanceTime
local _AsyncText
local _ComponentWithPassiveEffect
local _Text
local TextResource
local resourcePromise
local setTimeout
local Set

local JestGlobals = require("@pkg/@jsdotlua/jest-globals")
local jestExpect = JestGlobals.expect
local jest = JestGlobals.jest
local describe = JestGlobals.describe
local beforeEach = JestGlobals.beforeEach
local it = JestGlobals.it

local Promise = require("@pkg/@jsdotlua/promise")

local function loadModules(config)
	local enableProfilerTimer = (function()
		if config.enableProfilerTimer ~= nil then
			return config.enableProfilerTimer
		end
		return true
	end)()
	local enableProfilerCommitHooks = (function()
		if config.enableProfilerCommitHooks ~= nil then
			return config.enableProfilerCommitHooks
		end
		return true
	end)()
	local enableSchedulerTracing = (function()
		if config.enableSchedulerTracing ~= nil then
			return config.enableSchedulerTracing
		end
		return true
	end)()
	local replayFailedUnitOfWorkWithInvokeGuardedCallback = (function()
		if config.replayFailedUnitOfWorkWithInvokeGuardedCallback ~= nil then
			return config.replayFailedUnitOfWorkWithInvokeGuardedCallback
		end
		return false
	end)()
	local useNoopRenderer = (function()
		if config.useNoopRenderer ~= nil then
			return config.useNoopRenderer
		end
		return false
	end)()
	ReactFeatureFlags = require("@pkg/@jsdotlua/shared").ReactFeatureFlags

	ReactFeatureFlags.enableProfilerTimer = enableProfilerTimer
	ReactFeatureFlags.enableProfilerCommitHooks = enableProfilerCommitHooks
	ReactFeatureFlags.enableSchedulerTracing = enableSchedulerTracing
	ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback =
		replayFailedUnitOfWorkWithInvokeGuardedCallback

	local LuauPolyfill = require("@pkg/@jsdotlua/luau-polyfill")
	setTimeout = LuauPolyfill.setTimeout
	Set = LuauPolyfill.Set

	React = require("../init")
	Scheduler = require("@pkg/@jsdotlua/scheduler")
	_SchedulerTracing = Scheduler.tracing
	ReactCache = require("@pkg/@jsdotlua/react-cache")

	if useNoopRenderer then
		ReactNoop = require("@pkg/@jsdotlua/react-noop-renderer")
		ReactTestRenderer = nil
		ReactTestRendererAct = nil
	else
		ReactNoop = nil
		ReactTestRenderer = require("@pkg/@jsdotlua/react-test-renderer")
		ReactTestRendererAct = ReactTestRenderer.unstable_concurrentAct
	end

	AdvanceTime = React.Component:extend("AdvanceTime")
	AdvanceTime.defaultProps = {
		byAmount = 10,
		shouldComponentUpdate = true,
	}
	function AdvanceTime:shouldComponentUpdate(nextProps)
		return nextProps.shouldComponentUpdate
	end
	function AdvanceTime:render()
		-- Simulate time passing when self component is rendered
		Scheduler.unstable_advanceTime(self.props.byAmount)
		return self.props.children or nil
	end

	resourcePromise = nil

	TextResource = ReactCache.unstable_createResource(function(args)
		local text, ms = args[1], args[2] or 0
		resourcePromise = Promise.new(function(resolve, reject)
			setTimeout(function()
				Scheduler.unstable_yieldValue(
					string.format("Promise resolved [%s]", tostring(text))
				)
				resolve(text)
			end, ms)
		end)
		return resourcePromise
	end, function(args)
		local text = args[1]
		return text
	end)

	_AsyncText = function(props)
		local ms, text = props.ms, props.text
		local ok, result = pcall(function()
			TextResource.read({ text, ms })
			Scheduler.unstable_yieldValue(string.format("AsyncText [%s]", text))
			return text
		end)
		if not ok then
			local promise = result
			if typeof(promise.andThen) == "function" then
				Scheduler.unstable_yieldValue(string.format("Suspend [%s]", text))
			else
				Scheduler.unstable_yieldValue(string.format("Error [%s]", text))
			end
			error(promise)
		end
	end

	_Text = function(props)
		local text = props.text
		Scheduler.unstable_yieldValue(string.format("Text [%s]", text))
		return text
	end

	_ComponentWithPassiveEffect = function()
		-- Intentionally schedule a passive effect so the onPostCommit hook will be called.
		React.useEffect(function() end)
		return nil
	end
end

-- ROBLOX Test Noise: in upstream, jest setup config makes these tests hide
-- the error boundary warnings they trigger (scripts/jest/setupTests.js:72)
describe("Profiler", function()
	-- ROBLOX deviation: use faketimers instead
	-- local advanceTimeBy
	-- local currentTime

	describe("works in profiling and non-profiling bundles", function()
		for _, enableSchedulerTracing in { true, false } do
			for _, enableProfilerTimer in { true, false } do
				describe("enableSchedulerTracing:" .. (function()
					if enableSchedulerTracing then
						return "enabled"
					end
					return "disabled"
				end)() .. " enableProfilerTimer:" .. (function()
					if enableProfilerTimer then
						return "enabled"
					end
					return "disabled"
				end)() .. "}", function()
					-- ROBLOX deviation START: add condition, otherwise the suite will fail because of no tests
					if _G.__DEV__ and enableProfilerTimer then
						-- ROBLOX deviation END
						beforeEach(function()
							jest.resetModules()

							loadModules({
								enableSchedulerTracing = enableSchedulerTracing,
								enableProfilerTimer = enableProfilerTimer,
								-- ROBLOX TODO: set this explicitly to false until we have the correct HostConfig for the TestRenderer setup
								replayFailedUnitOfWorkWithInvokeGuardedCallback = false,
							})
						end)
						-- ROBLOX deviation START: add condition, otherwise the suite will fail because of no tests
					end
					-- ROBLOX deviation END

					-- This will throw in production too,
					-- But the test is only interested in verifying the DEV error message.
					if _G.__DEV__ and enableProfilerTimer then
						it("should warn if required params are missing", function()
							jestExpect(function()
								ReactTestRenderer.create(
									React.createElement(React.Profiler)
								)
							end).toErrorDev(
								'Profiler must specify an "id" as a prop',
								{
									withoutStack = true,
								}
							)
						end)

						it(
							"should support an empty Profiler (with no children)",
							function()
								jestExpect(function()
									ReactTestRenderer.create(
										React.createElement(React.Profiler, {
											id = "label",
											onRender = jest.fn(),
										})
									)
										:toJSON()
									-- ROBLOX TODO: toJSON needs to work, use toMatchSnapshot
								end).never.toThrow()
							end
						)

						it("should render children", function()
							local FunctionComponent = function(props)
								local label = props.label
								return React.createElement("span", nil, label)
							end
							local renderer = ReactTestRenderer.create(
								React.createElement(
									"div",
									nil,
									React.createElement("span", nil, "outside span"),
									React.createElement(
										React.Profiler,
										{ id = "label", onRender = jest.fn() },
										React.createElement("span", nil, "inside span"),
										React.createElement(FunctionComponent, {
											label = "function component",
										})
									)
								)
							)
							jestExpect(function()
								renderer:toJSON()
							end).never.toThrow()
							-- ROBLOX TODO: toJSON needs to work, use toMatchSnapshot
							--toMatchSnapshot()
						end)

						it("should support nested Profilers", function()
							local FunctionComponent = function(props)
								local label = props.label
								return React.createElement("div", nil, label)
							end
							local ClassComponent =
								React.Component:extend("ClassComponent")
							function ClassComponent:render()
								return React.createElement("block", nil, self.props.label)
							end
							local renderer = ReactTestRenderer.create(
								React.createElement(
									React.Profiler,
									{ id = "outer", onRender = jest.fn() },
									React.createElement(FunctionComponent, {
										label = "outer function component",
									}),
									React.createElement(
										React.Profiler,
										{ id = "inner", onRender = jest.fn() },
										React.createElement(ClassComponent, {
											label = "inner class component",
										}),
										React.createElement("span", nil, "inner span")
									)
								)
							)

							jestExpect(function()
								renderer:toJSON()
							end).never.toThrow()
							-- ROBLOX TODO: implement toJSON, use toMatchSnapshot when its available
							-- .toMatchSnapshot()
						end)
					end
				end)
			end
		end
	end)

	for _, enableSchedulerTracing in { true, false } do
		describe("onRender enableSchedulerTracing:" .. (function()
			if enableSchedulerTracing then
				return "enabled"
			end
			return "disabled"
		end)(), function()
			beforeEach(function()
				jest.resetModules()

				loadModules({
					enableSchedulerTracing = enableSchedulerTracing,
					-- ROBLOX TODO: set this explicitly to false until we have the correct HostConfig for the TestRenderer setup
					replayFailedUnitOfWorkWithInvokeGuardedCallback = false,
				})
			end)

			it("should handle errors thrown", function()
				local callback = jest.fn(function(id)
					if id == "throw" then
						error("expected")
					end
				end)

				local didMount = false
				local ClassComponent = React.Component:extend("ClassComponent")
				function ClassComponent:componentDidMount()
					didMount = true
				end
				function ClassComponent:render()
					return self.props.children
				end

				-- Errors thrown from onRender should not break the commit phase,
				-- Or prevent other lifecycles from being called.
				jestExpect(function()
					ReactTestRenderer.create(
						React.createElement(
							ClassComponent,
							nil,
							React.createElement(
								React.Profiler,
								{ id = "do-not-throw", onRender = callback },
								React.createElement(React.Profiler, {
									id = "throw",
									onRender = callback,
								}, React.createElement("div"))
							)
						)
					)
				end).toThrow("expected")
				jestExpect(didMount).toBe(true)
				jestExpect(callback).toHaveBeenCalledTimes(2)
			end)

			it("is not invoked until the commit phase", function()
				local callback = jest.fn()

				local Yield = function(props)
					local value = props.value
					Scheduler.unstable_yieldValue(value)
					return nil
				end

				ReactTestRenderer.create(
					React.createElement(
						React.Profiler,
						{ id = "test", onRender = callback },
						React.createElement(Yield, { value = "first" }),
						React.createElement(Yield, { value = "last" })
					),
					{
						unstable_isConcurrent = true,
					}
				)

				-- Times are logged until a render is committed.
				jestExpect(Scheduler).toFlushAndYieldThrough({ "first" })
				jestExpect(callback).toHaveBeenCalledTimes(0)
				jestExpect(Scheduler).toFlushAndYield({ "last" })
				jestExpect(callback).toHaveBeenCalledTimes(1)
			end)

			-- skipped translating some tests

			it("does not report work done on a sibling", function()
				local callback = jest.fn()

				local DoesNotUpdate = React.memo(function()
					Scheduler.unstable_advanceTime(10)
					return nil
				end, function()
					return true
				end)

				local updateProfilerSibling

				local function ProfilerSibling()
					local count, setCount = React.useState(0)
					updateProfilerSibling = function()
						setCount(count + 1)
					end
					return nil
				end

				local function App()
					return React.createElement(
						React.Fragment,
						nil,
						React.createElement(React.Profiler, {
							id = "test",
							onRender = callback,
						}, React.createElement(DoesNotUpdate)),
						React.createElement(ProfilerSibling)
					)
				end

				local renderer = ReactTestRenderer.create(React.createElement(App))

				jestExpect(callback).toHaveBeenCalledTimes(1)

				local call = callback.mock.calls[1]

				jestExpect(call).toHaveLength((function()
					if enableSchedulerTracing then
						return 7
					else
						return 6
					end
				end)())
				jestExpect(call[1]).toBe("test")
				jestExpect(call[2]).toBe("mount")
				jestExpect(call[3]).toBe(10) -- actual time
				jestExpect(call[4]).toBe(10) -- base time
				jestExpect(call[5]).toBe(0) -- start time
				jestExpect(call[6]).toBe(10) -- commit time
				jestExpect(call[7]).toEqual((function()
					if enableSchedulerTracing then
						return Set.new()
					else
						return nil
					end
				end)()) -- intersection events

				callback:mockReset()

				Scheduler.unstable_advanceTime(20) -- 10 -> 30

				renderer.update(React.createElement(App))

				-- ROBLOX deviation: we don't support dynamic/gated flags, so hard-code the path
				-- 						if (gate(flags => flags.new)) {
				-- None of the Profiler's subtree was rendered because App bailed out before the Profiler.
				-- So we expect onRender not to be called.
				jestExpect(callback).never.toHaveBeenCalled()
				-- 						} else {
				-- Updating a parent reports a re-render,
				-- since React technically did a little bit of work between the Profiler and the bailed out subtree.
				-- This is not optimal but it's how the old reconciler fork works.
				--   jestExpect(callback).toHaveBeenCalledTimes(1)

				--   call = callback.mock.calls[1]

				--   jestExpect(call).toHaveLength((function()
				-- 	if enableSchedulerTracing then
				-- 		return 7
				-- 	else
				-- 		return 6
				-- 	end
				-- 	end)())
				--   jestExpect(call[1]).toBe('test')
				--   jestExpect(call[2]).toBe('update')
				--   jestExpect(call[3]).toBe(0) -- actual time
				--   jestExpect(call[4]).toBe(10) -- base time
				--   jestExpect(call[5]).toBe(30) -- start time
				--   jestExpect(call[6]).toBe(30) -- commit time
				--   jestExpect(call[7]).toEqual((function()
				-- 	if enableSchedulerTracing then
				-- 		return {}
				-- 	else
				-- 		return nil
				-- 	end
				-- end)()) -- intersection events

				--   callback.mockReset()
				-- }

				Scheduler.unstable_advanceTime(20) -- 30 -> 50

				-- Updating a sibling should not report a re-render.
				ReactTestRendererAct(updateProfilerSibling)

				jestExpect(callback).never.toHaveBeenCalled()
			end)

			it("logs render times for both mount and update", function()
				local callback = jest.fn()

				Scheduler.unstable_advanceTime(5) -- 0 -> 5

				local renderer = ReactTestRenderer.create(
					React.createElement(
						React.Profiler,
						{ id = "test", onRender = callback },
						React.createElement(AdvanceTime)
					)
				)

				jestExpect(callback).toHaveBeenCalledTimes(1)

				local call = callback.mock.calls[1]

				jestExpect(call).toHaveLength((function()
					if enableSchedulerTracing then
						return 7
					else
						return 6
					end
				end)())
				jestExpect(call[1]).toBe("test")
				jestExpect(call[2]).toBe("mount")
				jestExpect(call[3]).toBe(10) -- actual time
				jestExpect(call[4]).toBe(10) -- base time
				jestExpect(call[5]).toBe(5) -- start time
				jestExpect(call[6]).toBe(15) -- commit time
				jestExpect(call[7]).toEqual((function()
					if enableSchedulerTracing then
						return Set.new()
					else
						return nil
					end
				end)()) -- intersection events

				callback.mockReset()

				Scheduler.unstable_advanceTime(20) -- 15 -> 35

				renderer.update(React.createElement(React.Profiler, {
					id = "test",
					onRender = callback,
				}, React.createElement(AdvanceTime)))

				jestExpect(callback).toHaveBeenCalledTimes(1)

				call = callback.mock.calls[1]

				jestExpect(call).toHaveLength((function()
					if enableSchedulerTracing then
						return 7
					else
						return 6
					end
				end)())
				jestExpect(call[1]).toBe("test")
				jestExpect(call[2]).toBe("update")
				jestExpect(call[3]).toBe(10) -- actual time
				jestExpect(call[4]).toBe(10) -- base time
				jestExpect(call[5]).toBe(35) -- start time
				jestExpect(call[6]).toBe(45) -- commit time
				jestExpect(call[7]).toEqual((function()
					if enableSchedulerTracing then
						return Set.new()
					else
						return nil
					end
				end)()) -- intersection events

				callback.mockReset()

				Scheduler.unstable_advanceTime(20) -- 45 -> 65

				renderer.update(React.createElement(React.Profiler, {
					id = "test",
					onRender = callback,
				}, React.createElement(AdvanceTime, { byAmount = 4 })))

				jestExpect(callback).toHaveBeenCalledTimes(1)

				call = callback.mock.calls[1]

				jestExpect(call).toHaveLength((function()
					if enableSchedulerTracing then
						return 7
					else
						return 6
					end
				end)())
				jestExpect(call[1]).toBe("test")
				jestExpect(call[2]).toBe("update")
				jestExpect(call[3]).toBe(4) -- actual time
				jestExpect(call[4]).toBe(4) -- base time
				jestExpect(call[5]).toBe(65) -- start time
				jestExpect(call[6]).toBe(69) -- commit time
				jestExpect(call[7]).toEqual((function()
					if enableSchedulerTracing then
						return Set.new()
					else
						return nil
					end
				end)()) -- intersection events
			end)

			it(
				"includes render times of nested Profilers in their parent times",
				function()
					local callback = jest.fn()

					Scheduler.unstable_advanceTime(5) -- 0 -> 5

					ReactTestRenderer.create(
						React.createElement(
							React.Fragment,
							nil,
							React.createElement(
								React.Profiler,
								{ id = "parent", onRender = callback },
								React.createElement(
									AdvanceTime,
									{ byAmount = 10 },
									React.createElement(
										React.Profiler,
										{ id = "child", onRender = callback },
										React.createElement(
											AdvanceTime,
											{ byAmount = 20 }
										)
									)
								)
							)
						)
					)

					jestExpect(callback).toHaveBeenCalledTimes(2)

					-- Callbacks bubble (reverse order).
					local childCall, parentCall =
						callback.mock.calls[1], callback.mock.calls[2]
					jestExpect(childCall[1]).toBe("child")
					jestExpect(parentCall[1]).toBe("parent")

					-- Parent times should include child times
					jestExpect(childCall[3]).toBe(20) -- actual time
					jestExpect(childCall[4]).toBe(20) -- base time
					jestExpect(childCall[5]).toBe(15) -- start time
					jestExpect(childCall[6]).toBe(35) -- commit time
					jestExpect(parentCall[3]).toBe(30) -- actual time
					jestExpect(parentCall[4]).toBe(30) -- base time
					jestExpect(parentCall[5]).toBe(5) -- start time
					jestExpect(parentCall[6]).toBe(35) -- commit time
				end
			)

			it("traces sibling Profilers separately", function()
				local callback = jest.fn()

				Scheduler.unstable_advanceTime(5) -- 0 -> 5

				ReactTestRenderer.create(
					React.createElement(
						React.Fragment,
						nil,
						React.createElement(React.Profiler, {
							id = "first",
							onRender = callback,
						}, React.createElement(AdvanceTime, { byAmount = 20 })),
						React.createElement(React.Profiler, {
							id = "second",
							onRender = callback,
						}, React.createElement(AdvanceTime, { byAmount = 5 }))
					)
				)

				jestExpect(callback).toHaveBeenCalledTimes(2)

				-- Callbacks bubble (reverse order).
				local firstCall, secondCall =
					callback.mock.calls[1], callback.mock.calls[2]
				jestExpect(firstCall[1]).toBe("first")
				jestExpect(secondCall[1]).toBe("second")

				-- Parent times should include child times
				jestExpect(firstCall[3]).toBe(20) -- actual time
				jestExpect(firstCall[4]).toBe(20) -- base time
				jestExpect(firstCall[5]).toBe(5) -- start time
				jestExpect(firstCall[6]).toBe(30) -- commit time
				jestExpect(secondCall[3]).toBe(5) -- actual time
				jestExpect(secondCall[4]).toBe(5) -- base time
				jestExpect(secondCall[5]).toBe(25) -- start time
				jestExpect(secondCall[6]).toBe(30) -- commit time
			end)

			it("does not include time spent outside of profile root", function()
				local callback = jest.fn()

				Scheduler.unstable_advanceTime(5) -- 0 -> 5

				ReactTestRenderer.create(
					React.createElement(
						React.Fragment,
						nil,
						React.createElement(AdvanceTime, { byAmount = 20 }),
						React.createElement(React.Profiler, {
							id = "test",
							onRender = callback,
						}, React.createElement(AdvanceTime, { byAmount = 5 })),
						React.createElement(AdvanceTime, { byAmount = 20 })
					)
				)

				jestExpect(callback).toHaveBeenCalledTimes(1)

				-- Callbacks bubble (reverse order).
				local call = callback.mock.calls[1]
				jestExpect(call[1]).toBe("test")
				jestExpect(call[3]).toBe(5) -- actual time
				jestExpect(call[4]).toBe(5) -- base time
				jestExpect(call[5]).toBe(25) -- start time
				jestExpect(call[6]).toBe(50) -- commit time
			end)

			it("is not called when blocked by sCU false", function()
				local callback = jest.fn()

				local instance
				local Updater = React.Component:extend("Updater")
				function Updater:init()
					self.state = {}
				end
				function Updater:render()
					instance = self
					return self.props.children
				end

				local renderer = ReactTestRenderer.create(
					React.createElement(
						React.Profiler,
						{ id = "outer", onRender = callback },
						React.createElement(
							Updater,
							nil,
							React.createElement(
								React.Profiler,
								{ id = "inner", onRender = callback },
								React.createElement("div")
							)
						)
					)
				)

				-- All profile callbacks are called for initial render
				jestExpect(callback).toHaveBeenCalledTimes(2)

				callback:mockReset()

				renderer.unstable_flushSync(function()
					instance:setState({
						count = 1,
					})
				end)

				-- Only call onRender for paths that have re-rendered.
				-- Since the Updater's props didn't change,
				-- React does not re-render its children.
				jestExpect(callback).toHaveBeenCalledTimes(1)
				jestExpect(callback.mock.calls[1][1]).toBe("outer")
			end)

			it(
				"decreases actual time but not base time when sCU prevents an update",
				function()
					local callback = jest.fn()

					Scheduler.unstable_advanceTime(5) -- 0 -> 5

					local renderer = ReactTestRenderer.create(
						React.createElement(
							React.Profiler,
							{ id = "test", onRender = callback },
							React.createElement(
								AdvanceTime,
								{ byAmount = 10 },
								React.createElement(
									AdvanceTime,
									{ byAmount = 13, shouldComponentUpdate = false }
								)
							)
						)
					)

					jestExpect(callback).toHaveBeenCalledTimes(1)

					Scheduler.unstable_advanceTime(30) -- 28 -> 58

					renderer.update(
						React.createElement(
							React.Profiler,
							{ id = "test", onRender = callback },
							React.createElement(
								AdvanceTime,
								{ byAmount = 4 },
								React.createElement(
									AdvanceTime,
									{ byAmount = 7, shouldComponentUpdate = false }
								)
							)
						)
					)

					jestExpect(callback).toHaveBeenCalledTimes(2)

					local mountCall, updateCall =
						callback.mock.calls[1], callback.mock.calls[2]

					jestExpect(mountCall[2]).toBe("mount")
					jestExpect(mountCall[3]).toBe(23) -- actual time
					jestExpect(mountCall[4]).toBe(23) -- base time
					jestExpect(mountCall[5]).toBe(5) -- start time
					jestExpect(mountCall[6]).toBe(28) -- commit time

					jestExpect(updateCall[2]).toBe("update")
					jestExpect(updateCall[3]).toBe(4) -- actual time
					jestExpect(updateCall[4]).toBe(17) -- base time
					jestExpect(updateCall[5]).toBe(58) -- start time
					jestExpect(updateCall[6]).toBe(62) -- commit time
				end
			)

			it("includes time spent in render phase lifecycles", function()
				local WithLifecycles = React.Component:extend("WithLifecycles")
				function WithLifecycles:init()
					self.state = {}
				end
				WithLifecycles.getDerivedStateFromProps = function()
					Scheduler.unstable_advanceTime(3)
					return nil
				end
				function WithLifecycles:shouldComponentUpdate()
					Scheduler.unstable_advanceTime(7)
					return true
				end
				function WithLifecycles:render()
					Scheduler.unstable_advanceTime(5)
					return nil
				end

				local callback = jest.fn()

				Scheduler.unstable_advanceTime(5) -- 0 -> 5

				local renderer = ReactTestRenderer.create(
					React.createElement(
						React.Profiler,
						{ id = "test", onRender = callback },
						React.createElement(WithLifecycles)
					)
				)

				Scheduler.unstable_advanceTime(15) -- 13 -> 28

				renderer.update(
					React.createElement(
						React.Profiler,
						{ id = "test", onRender = callback },
						React.createElement(WithLifecycles)
					)
				)

				jestExpect(callback).toHaveBeenCalledTimes(2)

				local mountCall, updateCall =
					callback.mock.calls[1], callback.mock.calls[2]

				jestExpect(mountCall[2]).toBe("mount")
				jestExpect(mountCall[3]).toBe(8) -- actual time
				jestExpect(mountCall[4]).toBe(8) -- base time
				jestExpect(mountCall[5]).toBe(5) -- start time
				jestExpect(mountCall[6]).toBe(13) -- commit time

				jestExpect(updateCall[2]).toBe("update")
				jestExpect(updateCall[3]).toBe(15) -- actual time
				jestExpect(updateCall[4]).toBe(15) -- base time
				jestExpect(updateCall[5]).toBe(28) -- start time
				jestExpect(updateCall[6]).toBe(43) -- commit time
			end)

			describe("with regard to interruptions", function()
				for _, replayFailedUnitOfWorkWithInvokeGuardedCallback in { true, false } do
					describe(
						"replayFailedUnitOfWorkWithInvokeGuardedCallback "
							.. (function()
								if replayFailedUnitOfWorkWithInvokeGuardedCallback then
									return "enabled"
								end
								return "disabled"
							end)(),
						function()
							beforeEach(function()
								jest.resetModules()

								loadModules({
									replayFailedUnitOfWorkWithInvokeGuardedCallback = replayFailedUnitOfWorkWithInvokeGuardedCallback,
								})
							end)

							it(
								"should accumulate actual time after an error handled by componentDidCatch()",
								function()
									local callback = jest.fn()

									local ThrowsError = function(props)
										local _unused = props.unused
										Scheduler.unstable_advanceTime(3)
										error("expected error")
									end

									local ErrorBoundary =
										React.Component:extend("ErrorBoundary")
									function ErrorBoundary:init()
										self.state = { error_ = nil }
									end
									function ErrorBoundary:componentDidCatch(error_)
										self:setState({ error_ = error_ })
									end
									function ErrorBoundary:render()
										Scheduler.unstable_advanceTime(2)
										return (function()
											if self.state.error_ == nil then
												return self.props.children
											end
											return React.createElement(
												AdvanceTime,
												{ byAmount = 20 }
											)
										end)()
									end

									Scheduler.unstable_advanceTime(5) -- 0 -> 5

									ReactTestRenderer.create(
										React.createElement(
											React.Profiler,
											{ id = "test", onRender = callback },
											React.createElement(
												ErrorBoundary,
												nil,
												React.createElement(
													AdvanceTime,
													{ byAmount = 9 }
												),
												React.createElement(ThrowsError)
											)
										)
									)

									jestExpect(callback).toHaveBeenCalledTimes(2)

									-- Callbacks bubble (reverse order).
									local mountCall, updateCall =
										callback.mock.calls[1], callback.mock.calls[2]

									-- The initial mount only includes the ErrorBoundary (which takes 2)
									-- But it spends time rendering all of the failed subtree also.
									jestExpect(mountCall[2]).toBe("mount")
									-- actual time includes: 2 (ErrorBoundary) + 9 (AdvanceTime) + 3 (ThrowsError)
									-- We don't count the time spent in replaying the failed unit of work (ThrowsError)
									jestExpect(mountCall[3]).toBe(14)
									-- base time includes: 2 (ErrorBoundary)
									-- Since the tree is empty for the initial commit
									jestExpect(mountCall[4]).toBe(2)
									-- start time
									jestExpect(mountCall[5]).toBe(5)
									-- commit time: 5 initially + 14 of work
									-- Add an additional 3 (ThrowsError) if we replayed the failed work
									jestExpect(mountCall[6]).toBe((function()
										if
											_G.__DEV__
											and replayFailedUnitOfWorkWithInvokeGuardedCallback
										then
											return 22
										end
										return 19
									end)())

									-- The update includes the ErrorBoundary and its fallback child
									jestExpect(updateCall[2]).toBe("update")
									-- actual time includes: 2 (ErrorBoundary) + 20 (AdvanceTime)
									jestExpect(updateCall[3]).toBe(22)
									-- base time includes: 2 (ErrorBoundary) + 20 (AdvanceTime)
									jestExpect(updateCall[4]).toBe(22)
									-- start time
									jestExpect(updateCall[5]).toBe((function()
										if
											_G.__DEV__
											and replayFailedUnitOfWorkWithInvokeGuardedCallback
										then
											return 22
										end
										return 19
									end)())

									-- commit time: 19 (startTime) + 2 (ErrorBoundary) + 20 (AdvanceTime)
									-- Add an additional 3 (ThrowsError) if we replayed the failed work
									jestExpect(updateCall[6]).toBe((function()
										if
											_G.__DEV__
											and replayFailedUnitOfWorkWithInvokeGuardedCallback
										then
											return 44
										end
										return 41
									end)())
								end
							)

							it(
								"should accumulate actual time after an error handled by getDerivedStateFromError()",
								function()
									local callback = jest.fn()

									local ThrowsError = function(props)
										local _unused = props.unused
										Scheduler.unstable_advanceTime(10)
										error("expected error")
									end

									local ErrorBoundary =
										React.Component:extend("ErrorBoundary")
									function ErrorBoundary:init()
										self.state = { error_ = nil }
									end
									function ErrorBoundary.getDerivedStateFromError(
										error_
									)
										return { error_ = error_ }
									end
									function ErrorBoundary:render()
										Scheduler.unstable_advanceTime(2)
										return (function()
											if self.state.error_ == nil then
												return self.props.children
											end
											return React.createElement(
												AdvanceTime,
												{ byAmount = 20 }
											)
										end)()
									end

									Scheduler.unstable_advanceTime(5) -- 0 -> 5

									ReactTestRenderer.create(
										React.createElement(
											React.Profiler,
											{ id = "test", onRender = callback },
											React.createElement(
												ErrorBoundary,
												nil,
												React.createElement(
													AdvanceTime,
													{ byAmount = 5 }
												),
												React.createElement(ThrowsError)
											)
										)
									)

									jestExpect(callback).toHaveBeenCalledTimes(1)

									-- Callbacks bubble (reverse order).
									local mountCall = callback.mock.calls[1]

									-- The initial mount includes the ErrorBoundary's error state,
									-- But it also spends actual time rendering UI that fails and isn't included.
									jestExpect(mountCall[2]).toBe("mount")
									-- actual time includes: 2 (ErrorBoundary) + 5 (AdvanceTime) + 10 (ThrowsError)
									-- Then the re-render: 2 (ErrorBoundary) + 20 (AdvanceTime)
									-- We don't count the time spent in replaying the failed unit of work (ThrowsError)
									jestExpect(mountCall[3]).toBe(39)
									-- base time includes: 2 (ErrorBoundary) + 20 (AdvanceTime)
									jestExpect(mountCall[4]).toBe(22)
									-- start time
									jestExpect(mountCall[5]).toBe(5)
									-- commit time
									jestExpect(mountCall[6]).toBe((function()
										if
											_G.__DEV__
											and replayFailedUnitOfWorkWithInvokeGuardedCallback
										then
											return 54
										end
										return 44
									end)())
								end
							)

							it(
								'should reset the fiber stack correct after a "complete" phase error',
								function()
									jest.resetModules()

									loadModules({
										useNoopRenderer = true,
										replayFailedUnitOfWorkWithInvokeGuardedCallback = replayFailedUnitOfWorkWithInvokeGuardedCallback,
									})

									-- Simulate a renderer error during the "complete" phase.
									-- This mimics behavior like React Native's View/Text nesting validation.
									ReactNoop.render(
										React.createElement(
											React.Profiler,
											{ id = "profiler", onRender = jest.fn() },
											React.createElement(
												"errorInCompletePhase",
												nil,
												"hi"
											)
										)
									)
									jestExpect(Scheduler).toFlushAndThrow(
										"Error in host config."
									)

									-- A similar case we've seen caused by an invariant in ReactDOM.
									-- It didn't reproduce without a host component inside.
									ReactNoop.render(
										React.createElement(
											React.Profiler,
											{ id = "profiler", onRender = jest.fn() },
											React.createElement(
												"errorInCompletePhase",
												nil,
												React.createElement("span", nil, "hi")
											)
										)
									)
									jestExpect(Scheduler).toFlushAndThrow(
										"Error in host config."
									)

									-- So long as the profiler timer's fiber stack is reset correctly,
									-- Subsequent renders should not error.
									ReactNoop.render(
										React.createElement(
											React.Profiler,
											{ id = "profiler", onRender = jest.fn() },
											React.createElement("span", nil, "hi")
										)
									)
									jestExpect(Scheduler).toFlushWithoutYielding()
								end
							)
						end
					)
				end
			end)
		end)
	end
end)
