$30 off During Our Annual Pro Sale. View Details »

🇮🇳 React India 2023

🇮🇳 React India 2023

ℹ️ Inside Fiber: the in-depth overview you wanted a TLDR for

We'll have an in-depth overview of the important concepts behind reconciliation and React Fiber. Then, we'll explore how React uses this algorithm and go through a few magic words we hear a lot, like coroutines, continuations, generators, and algebraic effects—and see how they all relate to React.

Matheus Albuquerque

October 03, 2023
Tweet

More Decks by Matheus Albuquerque

Other Decks in Programming

Transcript

  1. Hello, React India 👋 🇮🇳
    THE COMPUTER SCIENCE OF FIBERS • THE 3RD OF OCTOBER, 2023.

    View Slide

  2. MATHEUS ALBUQUERQUE • @ythecombinator
    THE COMPUTER SCIENCE OF


    FIBERS

    View Slide

  3. ↑ ALL THE LINKS! 🤓
    🧑🏫 @techlabs
    🐦 @ythecombinator
    👨💻 @medallia
    ⚡ Perf GDE
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  4. A bit of context
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  5. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  6. CONTINUATIONS
    ALGEBRAIC EFFECTS
    COROUTINES
    FIBERS
    THREADS
    GENERATORS

    View Slide

  7. ALGEBRAIC EFFECTS
    COROUTINES
    FIBERS
    CONTINUATIONS
    GENERATORS
    THREADS

    View Slide

  8. Fiber(s)
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  9. function add(x,y) {


    const result
    =
    x + y;


    return result;


    }


    add(2, 2)
    STACK FRAMES

    View Slide

  10. let frame: Frame
    =
    {


    return: frame,


    fn: add,


    parameters: [2, 2],


    localVariables: {


    result: 4,


    },


    }
    STACK FRAMES

    View Slide

  11. let frame: Frame
    =
    {


    return: frame,


    fn: add,


    parameters: [2, 2],


    localVariables: {


    result: 4,


    },


    }
    let fiber: Fiber
    =
    {


    return: fiber,


    component: Avatar,


    props: { id: 4 },


    state: {


    isLoaded: true,


    },


    }
    STACK FRAMES

    View Slide

  12. ↝ FIBER ARCHITECTURE ⇢ REACT-SPECIFIC
    IMPLEMENTATION OF A CALL-STACK-LIKE MODEL
    WHERE REACT HAS FULL CONTROL OF SCHEDULING
    WHAT SHOULD BE DONE


    ↝ FIBER ⇢ A STACK FRAME FOR A REACT
    COMPONENT
    FIBERS

    View Slide

  13. Fibers as


    Units of Work
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  14. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP
    WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE
    OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK
    NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.

    View Slide

  15. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP
    WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE
    OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK
    NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.

    View Slide

  16. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP
    WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE
    OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK
    NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.

    View Slide

  17. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP
    WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE
    OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK
    NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.

    View Slide

  18. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP
    WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE
    OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK
    NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE. A UNIT OF WORK.

    View Slide

  19. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP
    WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE
    OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK
    NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE. A UNIT OF WORK.
    AND THAT MAKES
    IT A CONVENIENT
    WAY TO TRACK,
    SCHEDULE, PAUSE
    AND ABORT THE
    WORK.

    View Slide

  20. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  21. Visualizing


    Units of Work
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  22. #EXPERIMENT 💻


    #1 Inspecting Elements

    View Slide

  23. View Slide

  24. View Slide

  25. let fiberNode
    =
    fiberRoot.current;


    let fibersMap
    =
    new Map();


    while (fiberNode) {


    if (fiberNode.stateNode
    !
    =
    =
    null) {


    fibersMap.set(fiberNode.stateNode, fiberNode);


    }


    if (fiberNode.child === null) {


    while (fiberNode
    !
    =
    =
    null
    &
    &
    fiberNode.sibling === null) {


    fiberNode
    =
    fiberNode.return;


    }


    fiberNode
    =
    fiberNode?.sibling;


    continue;


    }


    fiberNode
    =
    fiberNode.child;


    }

    View Slide

  26. let fiberNode
    =
    fiberRoot.current;


    let fibersMap
    =
    new Map();


    while (fiberNode) {


    if (fiberNode.stateNode
    !
    =
    =
    null) {


    fibersMap.set(fiberNode.stateNode, fiberNode);


    }


    if (fiberNode.child === null) {


    while (fiberNode
    !
    =
    =
    null
    &
    &
    fiberNode.sibling === null) {


    fiberNode
    =
    fiberNode.return;


    }


    fiberNode
    =
    fiberNode?.sibling;


    continue;


    }


    fiberNode
    =
    fiberNode.child;


    }
    🤯

    View Slide

  27. View Slide

  28. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  29. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  30. Manipulating
    Units of Work
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  31. #QUESTION 🤔


    Have you ever heard about
    homoiconicity?

    View Slide

  32. (let [x 1]


    (inc x)) ;
    =
    >
    2
    HOMOICONICITY

    View Slide

  33. (let [x 1]


    (inc x)) ;
    =
    >
    2
    HOMOICONICITY
    PERFORMS A TEMPORARY BINDING


    (BINDS X TO THE VALUE 1)

    View Slide

  34. INCREMENTS X TO GIVE
    THE RETURN VALUE OF 2
    (let [x 1]


    (inc x)) ;
    =
    >
    2
    HOMOICONICITY

    View Slide

  35. IT CAN BE THOUGHT OF AS A LIST WITH THREE
    ELEMENTS


    ↝ A SYMBOL NAMED LET


    ↝ A VECTOR WITH TWO ELEMENTS


    ↝ A LIST WITH TWO ELEMENTS
    HOMOICONICITY

    View Slide

  36. IT CAN BE THOUGHT OF AS A LIST WITH THREE
    ELEMENTS


    ↝ A SYMBOL NAMED LET


    ↝ A VECTOR WITH TWO ELEMENTS


    ↝ A LIST WITH TWO ELEMENTS
    HOMOICONICITY
    A SYMBOL (X) AND AN INTEGER
    A SYMBOL (INC) AND A SYMBOL (X)

    View Slide

  37. #QUOTE 🤔


    “…Homoiconicity is a property of some
    programming languages in which the code
    used to express a program is written using the
    data structures of that language.”


    — Wikipedia

    View Slide

  38. ↝ REACT ELEMENTS ARE JUST DATA


    ↝ JUST LIKE IN LISP, REACT COMPONENTS CAN
    MANIPULATE THEIR CHILDREN AND RETURN
    COMPLETELY DIFFERENT THINGS
    HOMOICONICITY

    View Slide

  39. #EXPERIMENT 💻


    #2 Pattern Matching in React

    View Slide

  40. #QUOTE 🤔


    “[…] Pattern matching consists of specifying
    patterns to which some data should conform
    and then checking to see if it does and
    deconstructing the data according to those
    patterns.”


    — Learn You a Haskell

    View Slide

  41. factorial
    :
    :
    (Integral a)
    =
    >
    a
    -
    >
    a


    factorial 0
    =
    1


    factorial n
    =
    n * factorial (n - 1)
    PATTERN MATCHING

    View Slide

  42. fib
    :
    :
    (Integral a)
    =
    >
    a
    -
    >
    a


    fib 0
    =
    1


    fib 1
    =
    1


    fib n | n
    >
    =
    2


    =
    fib (n-1) + fib (n-2)
    PATTERN MATCHING
    factorial


    factorial 0


    factorial n
    =

    View Slide

  43. PATTERN MATCHING

    View Slide

  44. /
    / .
    .
    .


    export function isWhen(


    child: ElementWithMetadataUnion


    ): child is ElementWithMetadata>
    >
    {


    return child.element.type === When;


    }


    /
    / .
    .
    .


    export function nodesToElementWithMetadata(


    children: ReactNode


    ) {


    return Children.toArray(children).map((element, idx)
    =
    >
    ({


    element: element,


    position: idx,


    })) as Array>
    >
    ;


    }


    /
    / .
    .
    .

    View Slide

  45. /
    / .
    .
    .


    export function isWhen(


    child: ElementWithMetadataUnion


    ): child is ElementWithMetadata>
    >
    {


    return child.element.type === When;


    }


    /
    / .
    .
    .


    export function nodesToElementWithMetadata(


    children: ReactNode


    ) {


    return Children.toArray(children).map((element, idx)
    =
    >
    ({


    element: element,


    position: idx,


    })) as Array>
    >
    ;


    }


    /
    / .
    .
    .

    View Slide

  46. const supportsSensor
    =
    ()
    =
    >
    Boolean(window.AmbientLightSensor);


    const AmbientLight
    =
    React.lazy(()
    =
    >
    import("./AmbientLight"));


    const Fallback
    =
    React.lazy(()
    =
    >
    import("./Fallback"));


    export default function MyComponent() {


    const { Match, When, Otherwise }
    =
    usePatternMatch();


    return (
































    );


    }
    PATTERN MATCHING

    View Slide

  47. const supportsSensor
    =
    ()
    =
    >
    Boolean(window.AmbientLightSensor);


    const AmbientLight
    =
    React.lazy(()
    =
    >
    import("./AmbientLight"));


    const Fallback
    =
    React.lazy(()
    =
    >
    import("./Fallback"));


    export default function MyComponent() {


    const { Match, When, Otherwise }
    =
    usePatternMatch();


    return (
































    );


    }
    PATTERN MATCHING


    + REACT.SUSPENSE


    + REACT.LAZY()


    = USERS DOWNLOAD ONLY
    THE COMPONENT BUNDLE
    THAT MATCHES

    View Slide

  48. const supportsSensor


    const AmbientLight


    const Fallback


    export default function MyComponent() {


    const { Match, When, Otherwise }


    return (
































    );


    }
    PATTERN MATCHING


    + REACT.SUSPENSE


    + REACT.LAZY()


    = USERS DOWNLOAD ONLY
    THE COMPONENT BUNDLE
    THAT MATCHES
    MANIPULATING BASED ON
    ELEMENTS DATA.

    View Slide

  49. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  50. USING FIBERS, REACT CAN:


    ↝ PAUSE, RESUME, AND RESTART RENDERING WORK
    ON COMPONENTS AS NEW UPDATES COME IN


    ↝ REUSE PREVIOUSLY COMPLETED WORK


    ↝ SPLIT WORK INTO CHUNKS AND PRIORITIZE TASKS
    BASED ON IMPORTANCE
    FIBERS IN REACT (RECAP)

    View Slide

  51. Fibers out
    there
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  52. ↝ A FIBER IS A GENERIC MODEL OF EXECUTION
    WHERE EACH UNIT WORKS TOGETHER
    COOPERATIVELY


    ↝ FIBERS ARE A COMMON RESOURCE IN SOME
    OPERATING SYSTEMS (E.G. WINDOWS) AND IN
    SOME PROGRAMMING LANGUAGES (E.G. OCAML)
    FIBERS OUT THERE

    View Slide

  53. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  54. Coroutines
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  55. View Slide

  56. #1 A GENERATOR (PRODUCER)
    THAT CAN ALSO CONSUME
    VALUES.
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  57. #1
    THE COMPUTER SCIENCE OF FIBERS
    ↝ JAVASCRIPT GENERATORS
    CAN CONSUME VALUES


    ↝ BY THIS DEFINITION,
    THEY ARE COROUTINES
    A GENERATOR (PRODUCER)
    THAT CAN ALSO CONSUME
    VALUES.

    View Slide

  58. #2 A GENERATOR THAT CAN
    RESOLVE ASYNCHRONOUS
    VALUES, LIKE ASYNC/AWAIT.
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  59. #2
    THE COMPUTER SCIENCE OF FIBERS
    ↝ THIS IS THE MOST COMMON
    MEANING OF “COROUTINE”
    IN THE JAVASCRIPT WORLD


    ↝ WE HAD CO AND BLUEBIRD,
    WHICH HAD ASYNC/AWAIT
    IMPLEMENTATIONS BASED
    ON GENERATORS
    VALUES, LIKE ASYNC/AWAIT.

    View Slide

  60. #3 A GENERATOR THAT CAN
    YIELD WITH A STACKFUL
    CONTINUATION
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  61. #3
    THE COMPUTER SCIENCE OF FIBERS
    ↝ "DEEP AWAIT"


    ↝ e.g. WITH SUSPENSE, WE
    CAN PAUSE
    RECONCILIATION AT ANY
    DEPTH
    A GENERATOR THAT CAN
    YIELD WITH A STACKFUL
    CONTINUATION

    View Slide

  62. Fibers
    CONTROL IS PASSED TO A
    SCHEDULER WHICH DETERMINES
    WHAT TO RUN NEXT
    ↝ = CONTROLLED AT THE LEVEL OF THE
    OPERATING SYSTEM OR FRAMEWORK


    ↝ E.G. NODE.JS EVENT LOOP

    View Slide

  63. Coroutines
    CONTROL IS PASSED TO THE
    CALLER AND HANDLED BY
    APPLICATION CODE
    Fibers
    CONTROL IS PASSED TO A
    SCHEDULER WHICH DETERMINES
    WHAT TO RUN NEXT

    View Slide

  64. Coroutines &
    React
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  65. COROUTINES APPEARED WHEN WORK ON FIBER
    WAS FIRST GOING AS A SPECIFIC COMPONENT
    TYPE.
    THE IDEA BEHIND COROUTINES — AS
    OPPOSED TO FIBERS — WAS TO GIVE
    COMPONENTS EXPLICIT CONTROL
    OVER YIELDING AND RESUMPTION.

    View Slide

  66. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  67. COROUTINES & REACT
    ↝ COROUTINES PER SI IN REACT NO LONGER EXIST.


    ↝ IT WILL BE FASCINATING TO SEE WHAT FORM
    COROUTINES TAKE WHEN THEY RETURN TO REACT
    FIBER.

    View Slide

  68. Coroutines &
    Concurrent
    React
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  69. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  70. View Slide

  71. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  72. function resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    resourcefulOperation(value);


    return {result};


    }

    View Slide

  73. #QUESTION 🤔


    How could we improve that?

    View Slide

  74. #EXPERIMENT 💻


    #3 Building a coroutines-based
    scheduler

    View Slide

  75. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  76. View Slide

  77. function resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    resourcefulOperation(value);


    return {result};


    }

    View Slide

  78. function* resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    while (true) {


    yield;


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    }


    const initialValue
    =
    0;


    const scheduler
    =
    new Scheduler(resourcefulOperation, initialValue);


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    scheduler.performUnitOfWork(value);


    return {result};


    }

    View Slide

  79. function* resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    while (true) {


    yield;


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    }


    const initialValue
    =
    0;


    const scheduler
    =
    new Scheduler(resourcefulOperation, initialValue);


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    scheduler.performUnitOfWork(value);


    return {result};


    }
    PROMOTED TO A GENERATOR
    YIELDING EXECUTION
    DOING CONCURRENT TASKS

    View Slide

  80. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  81. enum SchedulerState {


    IDLE
    =
    "IDLE",


    PENDING
    =
    "PENDING",


    DONE
    =
    "DONE",


    }


    class Scheduler {


    state: SchedulerState;


    result: T;


    worker: (data: T)
    =
    >
    Generator;


    iterator: Generator;


    constructor(worker: (data: T)
    =
    >
    Generator, initialResult: T) {


    this.state
    =
    SchedulerState.IDLE;


    this.worker
    =
    worker;


    this.result
    =
    initialResult;


    }


    performUnitOfWork(data: T) {


    switch (this.state) {


    case "IDLE":


    this.state
    =
    SchedulerState.PENDING;


    this.iterator
    =
    this.worker(data);


    throw Promise.resolve();


    case "PENDING":


    const { value, done }
    =
    this.iterator.next();


    if (done) {


    this.result
    =
    value;


    this.state
    =
    SchedulerState.DONE;


    return value;


    }


    throw Promise.resolve();


    case "DONE":


    this.state
    =
    SchedulerState.IDLE;


    return this.result;


    }


    }


    }

    View Slide

  82. performUnitOfWork(data: T) {


    switch (this.state) {


    case "IDLE":


    this.state
    =
    SchedulerState.PENDING;


    this.iterator
    =
    this.worker(data);


    throw Promise.resolve();


    case "PENDING":


    const { value, done }
    =
    this.iterator.next();


    if (done) {


    this.result
    =
    value;


    this.state
    =
    SchedulerState.DONE;


    return value;


    }


    throw Promise.resolve();


    case "DONE":


    this.state
    =
    SchedulerState.IDLE;


    return this.result;


    }


    }

    View Slide

  83. DID WE JUST


    useTransition’ED? 🤔

    View Slide

  84. function resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    resourcefulOperation(value);


    return {result};


    }

    View Slide

  85. function resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    function ResourcefulComponent(props: { value: number }) {


    const [_, startTransition]
    =
    useTransition();


    const [result, setResult]
    =
    useState("");


    useEffect(()
    =
    >
    {


    startTransition(()
    =
    >
    {


    const newResult
    =
    resourcefulOperation(props.value);


    setResult(newResult);


    });


    }, [props.value]);


    return {result};


    }

    View Slide

  86. YES, WE DID 🤓
    WITH OUR OWN, COROUTINES-BASED, SCHEDULER

    View Slide

  87. ↝ A COOPERATIVE MULTITASKING MODEL


    ↝ A SINGLE INTERRUPTIBLE RENDERING THREAD


    ↝ RENDERING CAN BE INTERLEAVED WITH OTHER
    MAIN THREAD TASKS AND OTHER REACT RENDERS


    ↝ AN UPDATE CAN HAPPEN IN THE BACKGROUND
    WITHOUT BLOCKING THE RESPONSE TO NEW INPUT
    COROUTINES & SCHEDULING

    View Slide

  88. ↓ ORIGINAL RENDER TASK
    USER INPUT →
    ↑ HIGHER PRIORITY RENDER TASK
    ↓ RESUME ORIGINAL RENDER TASK

    View Slide

  89. ↝ IT YIELDS EXECUTION IS BACK TO THE MAIN
    THREAD EVERY 5MS


    ↝ IT'S SMALLER THAN A SINGLE FRAME EVEN ON
    120FPS, SO IT WON'T BLOCK ANIMATIONS


    ↝ IN PRACTICE, RENDERING IS INTERRUPTIBLE
    COROUTINES & SCHEDULING

    View Slide

  90. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  91. Coroutines out
    there
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  92. ↝ ASYNCHRONY IN JAVASCRIPT IS CONTAGIOUS


    ↝ IF ANY FUNCTION IS ASYNC, THEN EVERYTHING
    THAT CALLS IT MUST ALSO BE ASYNC…


    ↝ …AND SO ON UNTIL THE ENTIRE PROGRAM
    IS ASYNCHRONOUS 🤷
    ASYNCHRONY & JS

    View Slide

  93. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  94. ↝ ASYNCHRONY IN JAVASCRIPT ISN’T FREE


    ↝ EVERY ASYNCHRONOUS FUNCTION CALL HAS TO:


    ↝ ALLOCATE CALLBACKS & STORE THEM SOMEWHERE


    ↝ TAKE A TRIP BACK TO THE EVENT LOOP BEFORE
    INVOKING THOSE CALLBACKS
    ASYNCHRONY & JS

    View Slide

  95. View Slide

  96. ↝ ITS API HAS TWO MAIN FUNCTIONS FOR
    COMPILING SASS FILES: ONE SYNC AND ONE
    ASYNC


    ↝ THE ASYNC ONE BECAME WIDELY USED IN
    PRACTICE BECAUSE IT ENABLED ASYNC PLUGINS
    (E.G. WEBPACK’S SASS-LOADER)
    ASYNCHRONY & SASS

    View Slide

  97. ↝ FOR NODE SASS, THE PERFORMANCE DIFFERENCE
    WAS NEGLIGIBLE, BECAUSE IT WAS BUILT ON C++


    ↝ HOWEVER, DART SASS RUNS AS PURE JAVASCRIPT,
    WHICH MAKES IT SUBJECT TO JAVASCRIPT’S
    ASYNC RULES
    ASYNCHRONY & SASS

    View Slide

  98. ↝ THE ASYNC VERSION IN DART SASS WAS 2-3X
    SLOWER THAN THE SYNC ONE


    ↝ THEY STARTED USING NODE-FIBERS TO IMPLEMENT
    THE ASYNC API USING THE FAST, SYNC, CODE
    ASYNCHRONY & SASS

    View Slide

  99. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  100. View Slide

  101. Effect Handlers
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  102. 🤯
    APPROACH TO REASONING ABOUT COMPUTATIONAL
    EFFECTS IN PURE CONTEXTS


    ↝ EFFECT ⇢ A SET OF OPERATIONS


    ↝ EFFECT HANDLER ⇢ RESPONSIBLE FOR HANDLING
    THE SEMANTICS OF HOW TO IMPLEMENT EFFECTS
    EFFECT HANDLERS

    View Slide

  103. (* state.eff *)


    type user
    =
    string * int


    effect Get: user


    effect Set: user
    -
    >
    unit
    🤯
    EFFECT HANDLERS IN EFF

    View Slide

  104. (* state.eff *)


    type user
    =
    string * int


    effect Get: user


    effect Set: user
    -
    >
    unit
    A USER WITH A NAME AND AGE
    EFFECT HANDLERS IN EFF

    View Slide

  105. (* state.eff *)


    type user
    =
    string * int


    effect Get: user


    effect Set: user
    -
    >
    unit
    WE DEFINE EFFECTS WITH THE effect
    KEYWORD AND A TYPE SIGNATURE.
    EFFECT HANDLERS IN EFF

    View Slide

  106. let state
    =
    handler


    | y
    -
    >
    fun currentState
    -
    >
    (y, currentState)


    | effect Get k
    -
    >
    (fun currentState
    -
    >
    (continue k currentState) currentState)


    | effect (Set newState) k
    -
    >
    (fun _
    -
    >
    (continue k ()) newState)


    ;;
    🤯
    EFFECT HANDLERS IN EFF

    View Slide

  107. let state
    =
    handler


    | y
    -
    >
    fun currentState
    -
    >
    (y, currentState)


    | effect Get k
    -
    >
    (fun currentState
    -
    >
    (continue k currentState) currentState)


    | effect (Set newState) k
    -
    >
    (fun _
    -
    >
    (continue k ()) newState)


    ;;
    WE HAVE A handler WITH THREE BRANCHES,
    AND ALL OF THEM RETURN A FUNCTION.
    EFFECT HANDLERS IN EFF

    View Slide

  108. let state
    =
    handler


    | y
    -
    >
    fun currentState
    -
    >
    (y, currentState)


    | effect Get k
    -
    >
    (fun currentState
    -
    >
    (continue k currentState) currentState)


    | effect (Set newState) k
    -
    >
    (fun _
    -
    >
    (continue k ()) newState)


    ;;
    NO EFFECT (WHEN WE REACH THE END OF THE BLOCK).


    y IS THE RETURN VALUE.
    EFFECT HANDLERS IN EFF

    View Slide

  109. let state
    =
    handler


    | y
    -
    >
    fun currentState
    -
    >
    (y, currentState)


    | effect Get k
    -
    >
    (fun currentState
    -
    >
    (continue k currentState) currentState)


    | effect (Set newState) k
    -
    >
    (fun _
    -
    >
    (continue k ()) newState)


    ;;
    MATCHING OUR EFFECTS.
    EFFECT HANDLERS IN EFF

    View Slide

  110. let state
    =
    handler


    | y
    -
    >
    fun currentState
    -
    >
    (y, currentState)


    | effect Get k
    -
    >
    (fun currentState
    -
    >
    (continue k currentState) currentState)


    | effect (Set newState) k
    -
    >
    (fun _
    -
    >
    (continue k ()) newState)


    ;;
    k IS A CONTINUATION. IT REPRESENTS THE REST OF THE
    COMPUTATION AFTER WHERE WE PERFORM AN EFFECT.
    EFFECT HANDLERS IN EFF

    View Slide

  111. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  112. function getName(user) {


    let name
    =
    user.name;


    if (name === null) {


    name
    =
    perform 'ask_name';


    }


    return name;


    }


    const arya
    =
    { name: null, friendNames: [] };


    const gendry
    =
    { name: 'Gendry', friendNames: [] };


    try {


    getName(arya);


    }


    handle (effect) {


    if (effect === 'ask_name') {


    resume with 'Arya Stark';


    }


    }

    View Slide

  113. function getName(user) {


    let name
    =
    user.name;


    if (name === null) {


    name
    =
    perform 'ask_name';


    }


    return name;


    }


    const arya
    =
    { name: null, friendNames: [] };


    const gendry
    =
    { name: 'Gendry', friendNames: [] };


    try {


    getName(arya);


    }


    handle (effect) {


    if (effect === 'ask_name') {


    resume with 'Arya Stark';


    }


    }

    View Slide

  114. function getName(user) {


    let name
    =
    user.name;


    if (name === null) {


    name
    =
    perform 'ask_name';


    }


    return name;


    }


    const arya
    =
    { name: null, friendNames: [] };


    const gendry
    =
    { name: 'Gendry', friendNames: [] };


    try {


    getName(arya);


    }


    handle (effect) {


    if (effect === 'ask_name') {


    resume with 'Arya Stark';


    }


    }
    THROW → PERFORM
    CATCH → HANDLE
    LETS US JUMP BACK TO WHERE WE
    PERFORMED THE EFFECT

    View Slide

  115. ↝ IT DOESN'T REALLY MATTER HOW WE HOLD STATE.
    IF WE WERE TO CHANGE IN THE FUTURE, WE’D
    NEED TO START HANDLING PROMISES, WHICH
    WOULD REQUIRE CHANGES ACROSS EVERYTHING.


    ↝ WITH ALGEBRAIC EFFECTS, WE CAN SIMPLY STOP
    THE CURRENT PROCESS ALTOGETHER UNTIL OUR
    EFFECTS ARE FINISHED.
    EFFECT HANDLERS

    View Slide

  116. Effect
    handlers in
    React
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  117. #1
    THE COMPUTER SCIENCE OF FIBERS
    LAYOUT
    ALGORITHM

    View Slide

  118. THE REACT TEAM APPARENTLY
    SPENT SOME TIME
    EXPERIMENTING WITH EFFECT-
    HANDLER CONTROL STRUCTURES
    FOR MANAGING LAYOUT

    View Slide

  119. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  120. #2 CONTEXT API
    DRAFTS
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  121. THEY’VE ALSO REMODELED THE CONTEXT
    API USING ALGEBRAIC EFFECTS

    View Slide

  122. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  123. #3 SIDE EFFECTS
    WITHIN A
    COMPONENT
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  124. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  125. function ThemeBorderColorRequest() { }


    function FancyBox(children) {


    const color
    =
    raise new ThemeBorderColorRequest();


    return {


    borderWidth: '1px',


    borderColor: color,


    children: children


    };


    }


    function BlueTheme(children) {


    return try {


    children();


    } catch effect ThemeBorderColorRequest
    -
    >
    [, continuation] {


    continuation('blue');


    }


    }


    function App(data) {


    return BlueTheme(


    FancyUserList.bind(null, data.users)


    );


    }

    View Slide

  126. function ThemeBorderColorRequest() { }


    function FancyBox(children) {


    const color
    =
    raise new ThemeBorderColorRequest();


    return {


    borderWidth: '1px',


    borderColor: color,


    children: children


    };


    }


    function BlueTheme(children) {


    return try {


    children();


    } catch effect ThemeBorderColorRequest
    -
    >
    [, continuation] {


    continuation('blue');


    }


    }


    function App(data) {


    return BlueTheme(


    FancyUserList.bind(null, data.users)


    );


    }
    THROW → RAISE
    CATCH → CATCH EFFECT

    View Slide

  127. #4 HOOKS


    API
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  128. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  129. SEBASTIAN POINTS THAT
    “CONCEPTUALLY, HOOKS ARE
    ALGEBRAIC EFFECTS”.

    View Slide

  130. HOOKS API
    ↝ ALGEBRAIC EFFECTS = A SET OF OPERATIONS AND
    A SET OF EFFECT HANDLERS


    ↝ THE OPERATIONS HERE ARE OUR HOOKS (E.G.
    useState, useEffect, AND SO ON)


    ↝ WE HAVE TO SET UP HANDLERS IN EFF; IN REACT
    THEY'RE SET UP AS PART OF THE RENDER CYCLE

    View Slide

  131. HOOKS API
    ↝ REACT IS RESPONSIBLE FOR MUCH OF THE
    IMPLEMENTATION OF WHEN/HOW OUR EFFECTS RUN


    ↝ IT ALLOWS US TO STASH ENORMOUS AMOUNTS OF
    COMPLEXITY WITHIN REACT


    ↝ BY SPLITTING EFFECTS AND RENDERING, WE
    ALLOW IT TO RELIEVE US OF SOME COMPLEXITY

    View Slide

  132. #5 SUSPENSE
    INTERNALS
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  133. #QUESTION 🤔


    Have you ever built any suspense-
    ready API?

    View Slide

  134. View Slide

  135. View Slide

  136. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  137. A COMPONENT IS ABLE TO
    SUSPEND THE FIBER IT IS
    RUNNING IN BY THROWING A
    PROMISE, WHICH IS CAUGHT
    AND HANDLED BY THE
    FRAMEWORK.

    View Slide

  138. A COMPONENT IS ABLE TO
    SUSPEND THE FIBER IT IS
    RUNNING IN BY THROWING A
    PROMISE, WHICH IS CAUGHT
    AND HANDLED BY THE
    FRAMEWORK.
    THROW → HANDLE → RESUME


    PATTERN.

    View Slide

  139. Effect
    handlers out
    there
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  140. EFFECT HANDLERS OUT THERE

    View Slide

  141. EFFECT HANDLERS OUT THERE

    View Slide

  142. EFFECT HANDLERS OUT THERE

    View Slide

  143. Continuations
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  144. #QUOTE 🤔


    “At my heart, I am something like the goto
    instruction; my creation sets the label, and my
    methods do the jump. However, this is a really
    powerful kind of goto instruction. […]”


    — GNU Smalltalk Continuation documentation

    View Slide

  145. ↝ IT’S AN ABSTRACTION THAT REPRESENTS THE
    REMAINING STEPS IN A COMPUTATION,
    AFTER WHERE WE PERFORM AN EFFECT.


    ↝ IT'S A CONTROL FLOW PRIMITIVE.


    ↝ DIFFERENT FROM goto. ALL THE VARIABLES,
    POINTERS, ETC. ARE VALID.
    CONTINUATIONS

    View Slide

  146. CONTINUATIONS IN REACT

    View Slide

  147. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  148. function performWork(deadline) {


    while (tasks.length > 0) {


    const task
    =
    tasks.shift();


    doTask(task);


    if (


    tasks.length > 0
    &
    &


    !deadline.didTimeout
    &
    &


    deadline.timeRemaining()
    <
    =
    0


    ) {


    return performWork;


    }


    }


    }


    scheduleWork(performWork);
    CONTINUATIONS IN REACT

    View Slide

  149. ↝ IT HANDLES A QUEUE OF TASKS IN A WHILE LOOP


    ↝ IF THERE ARE STILL TASKS ON THE QUEUE, IT
    RETURNS performWork AND SCHEDULE IT FOR
    RESUMPTION AT SOME LATER TIME


    ↝ IN THIS CONTEXT, IT REPRESENTS THE
    CONTINUATION OF A QUEUE OF TASKS
    CONTINUATIONS IN REACT

    View Slide

  150. CONTINUATIONS ON THE WEB

    View Slide

  151. async function doWork() {


    while (true) {


    let hasMoreWork
    =
    doSomeWork();


    if (!hasMoreWork) {


    return;


    }


    if (!navigator.scheduling.isInputPending()) {


    continue;


    }


    await scheduler.yield();


    }


    }
    🤯
    CONTINUATIONS ON THE WEB

    View Slide

  152. THE COMPUTER SCIENCE OF FIBERS

    View Slide

  153. CONTINUATIONS OUT THERE

    View Slide

  154. THE COMPUTER SCIENCE OF FIBERS
    Closing Notes

    View Slide

  155. #1 REACT FIBER WAS A REWRITE
    OF REACT FOCUSED ON
    GIVING MORE LOW-LEVEL
    CONTROL OVER PROGRAM
    EXECUTION
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  156. #1
    THE COMPUTER SCIENCE OF FIBERS
    ↝ FIBERS AS A LOW-LEVEL
    COOPERATIVE WAY TO
    MODEL EXECUTION


    ↝ ALGEBRAIC EFFECTS AS A
    WAY TO HANDLE EFFECTS
    WHERE THESE AND THEIR
    BEHAVIOR ARE
    INDEPENDENT
    EXECUTION

    View Slide

  157. #2
    THE COMPUTER SCIENCE OF FIBERS
    REACT TRIES TO ADDRESS
    THE LACK OF SOME
    JAVASCRIPT FEATURES/
    LANGUAGE-LEVEL RESOURCES
    BY IMPLEMENTING SOME
    ALTERNATIVE SOLUTIONS TO
    ACHIEVE SIMILAR BEHAVIORS


    E.G. EFFECT HANDLERS & CONTINUATIONS

    View Slide

  158. #3
    THE COMPUTER SCIENCE OF FIBERS
    UNDERSTANDING SOME OF
    THESE CONCEPTS GIVES US A
    BETTER MENTAL MODEL FOR
    WHAT SOME REACT FEATURES
    ARE DOING BEHIND THE
    SCENES


    E.G. HOOKS AND EFFECT HANDLERS

    View Slide

  159. #4
    THE COMPUTER SCIENCE OF FIBERS
    UNDERSTANDING THESE
    INTERNALS AND THEIR
    RATIONALES HELPS US
    IMPLEMENT OUR OWN
    ABSTRACTIONS


    E.G. THE COROUTINES-BASED SCHEDULER &
    THE PATTERN MATCHING COMPONENTS

    View Slide

  160. View Slide

  161. #5 THE FACT WE'RE DISCUSSING
    ALL OF THESE TOPICS SHOWS
    THAT REACT ACTS AS A
    DEMOCRATIC AGENT FOR THIS
    KIND OF KNOWLEDGE IN THE
    FRONT-END WORLD
    THE COMPUTER SCIENCE OF FIBERS

    View Slide

  162. THAT’S ALL, FOLKS!


    THANKS! 👋 🇮🇳


    QUESTIONS?
    MATHEUS ALBUQUERQUE • @ythecombinator
    ↑ ALL THE LINKS! 🤓
    THE COMPUTER SCIENCE OF FIBERS

    View Slide