function runTest(listItem, callback) { try { callback(); listItem.className = 'correct'; listItem.setAttribute('data-value', 'All checks pass'); } catch (error) { listItem.className = 'incorrect'; listItem.setAttribute('data-value', error); } } function runAllTests() { try { checkSchedulerAPI(); } finally { try { checkSchedulerTracingAPI(); } finally { try { checkSchedulerTracingSubscriptionsAPI(); } finally { checkEndToEndIntegration(); } } } } function checkSchedulerAPI() { runTest(document.getElementById('checkSchedulerAPI'), () => { if ( typeof Scheduler === 'undefined' || typeof Scheduler.unstable_now !== 'function' || typeof Scheduler.unstable_scheduleCallback !== 'function' || typeof Scheduler.unstable_cancelCallback !== 'function' ) { throw 'API is not defined'; } const abs = Math.abs(Scheduler.unstable_now() - performance.now()); if (typeof abs !== 'number' || Number.isNaN(abs) || abs > 5) { throw 'API does not work'; } // There is no real way to verify that the two APIs are connected. }); } function checkSchedulerTracingAPI() { runTest(document.getElementById('checkSchedulerTracingAPI'), () => { if ( typeof SchedulerTracing === 'undefined' || typeof SchedulerTracing.unstable_clear !== 'function' || typeof SchedulerTracing.unstable_getCurrent !== 'function' || typeof SchedulerTracing.unstable_getThreadID !== 'function' || typeof SchedulerTracing.unstable_trace !== 'function' || typeof SchedulerTracing.unstable_wrap !== 'function' ) { throw 'API is not defined'; } try { let interactionsSet; SchedulerTracing.unstable_trace('test', 123, () => { interactionsSet = SchedulerTracing.unstable_getCurrent(); }); if (interactionsSet.size !== 1) { throw null; } const interaction = Array.from(interactionsSet)[0]; if (interaction.name !== 'test' || interaction.timestamp !== 123) { throw null; } } catch (error) { throw 'API does not work'; } const ForwardedSchedulerTracing = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.SchedulerTracing; if ( SchedulerTracing.unstable_getThreadID() === ForwardedSchedulerTracing.unstable_getThreadID() ) { throw 'API forwarding is broken'; } }); } function checkSchedulerTracingSubscriptionsAPI() { runTest( document.getElementById('checkSchedulerTracingSubscriptionsAPI'), () => { if ( typeof SchedulerTracing === 'undefined' || typeof SchedulerTracing.unstable_subscribe !== 'function' || typeof SchedulerTracing.unstable_unsubscribe !== 'function' ) { throw 'API is not defined'; } const onInteractionScheduledWorkCompletedCalls = []; const onInteractionTracedCalls = []; const onWorkCanceledCalls = []; const onWorkScheduledCalls = []; const onWorkStartedCalls = []; const onWorkStoppedCalls = []; const subscriber = { onInteractionScheduledWorkCompleted: (...args) => onInteractionScheduledWorkCompletedCalls.push(args), onInteractionTraced: (...args) => onInteractionTracedCalls.push(args), onWorkCanceled: (...args) => onWorkCanceledCalls.push(args), onWorkScheduled: (...args) => onWorkScheduledCalls.push(args), onWorkStarted: (...args) => onWorkStartedCalls.push(args), onWorkStopped: (...args) => onWorkStoppedCalls.push(args), }; try { SchedulerTracing.unstable_subscribe(subscriber); SchedulerTracing.unstable_trace('foo', 123, () => {}); SchedulerTracing.unstable_unsubscribe(subscriber); if (onInteractionTracedCalls.length !== 1) { throw null; } const interaction = onInteractionTracedCalls[0][0]; if (interaction.name !== 'foo' || interaction.timestamp !== 123) { throw null; } SchedulerTracing.unstable_trace('bar', 456, () => {}); if (onInteractionTracedCalls.length !== 1) { throw null; } } catch (error) { throw 'API does not forward methods'; } const ForwardedSchedulerTracing = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED .SchedulerTracing; try { ForwardedSchedulerTracing.unstable_subscribe(subscriber); SchedulerTracing.unstable_trace('foo', 123, () => {}); ForwardedSchedulerTracing.unstable_trace('bar', 456, () => {}); SchedulerTracing.unstable_unsubscribe(subscriber); if (onInteractionTracedCalls.length !== 3) { throw null; } const interactionFoo = onInteractionTracedCalls[1][0]; const interactionBar = onInteractionTracedCalls[2][0]; if ( interactionFoo.name !== 'foo' || interactionFoo.timestamp !== 123 || interactionBar.name !== 'bar' || interactionBar.timestamp !== 456 ) { throw null; } ForwardedSchedulerTracing.unstable_trace('baz', 789, () => {}); if (onInteractionTracedCalls.length !== 3) { throw null; } } catch (error) { throw 'API forwarding is broken'; } } ); } function checkEndToEndIntegration() { runTest(document.getElementById('checkEndToEndIntegration'), () => { try { const onRenderCalls = []; const onRender = (...args) => onRenderCalls.push(args); const container = document.createElement('div'); SchedulerTracing.unstable_trace('render', 123, () => { ReactDOM.render( React.createElement( React.Profiler, {id: 'profiler', onRender}, React.createElement('div', null, 'hi') ), container ); }); if (container.textContent !== 'hi') { throw null; } if (onRenderCalls.length !== 1) { throw null; } const call = onRenderCalls[0]; if (call.length !== 7) { throw null; } const interaction = Array.from(call[6])[0]; if (interaction.name !== 'render' || interaction.timestamp !== 123) { throw null; } } catch (error) { throw 'End to end integration is broken'; } }); }