Upgrade to Pro — share decks privately, control downloads, hide ads and more …

🇪🇸 React Alicante 2022

🇪🇸 React Alicante 2022

ℹ️ 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 01, 2022
Tweet

More Decks by Matheus Albuquerque

Other Decks in Technology

Transcript

  1. ¡Hola, React Alicante! ✋ 🇪🇸
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR • THE 28TH OF JUNE, 2022.

    View Slide

  2. MATHEUS ALBUQUERQUE
    INSIDE FIBER
    THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  3. I’M MATHEUS 🙋
    ↝ @YTHECOMBINATOR ON THE
    WEB


    ↝ SR. SOFTWARE ENGINEER
    @MEDALLIA


    ↝ MENTOR @TECHLABS

    View Slide

  4. Disclaimers
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  5. #1
    REACT SOURCE
    CODE IS
    CONSTANTLY
    CHANGING, AND
    SOME THOUGHTS
    ARE SPECULATIONS
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  6. #2
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    🤯 = FURTHER
    DISCUSSIONS
    AFTER THE
    SESSION

    View Slide

  7. A bit of context
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  8. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  9. CONTINUATIONS
    ALGEBRAIC EFFECTS
    COROUTINES
    FIBERS
    THREADS
    GENERATORS

    View Slide

  10. ALGEBRAIC EFFECTS
    COROUTINES
    FIBERS
    GENERATORS
    CONTINUATIONS
    THREADS

    View Slide

  11. Fiber(s)
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  12. function add(x,y) {


    const result
    =
    x + y;


    return result;


    }


    add(2, 2)
    STACK FRAMES

    View Slide

  13. let frame: Frame
    =
    {


    return: frame,


    fn: add,


    parameters: [2, 2],


    localVariables: {


    result: 4,


    },


    }
    STACK FRAMES

    View Slide

  14. 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

  15. ↝ 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

  16. Fibers as


    Units of Work
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    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.

    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.

    View Slide

  20. 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

  21. 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

  22. 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

  23. Visualizing


    Units of Work
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  24. #EXPERIMENT 💻


    #1 Inspecting Elements

    View Slide

  25. View Slide

  26. View Slide

  27. 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

  28. 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

  29. View Slide

  30. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  31. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  32. Manipulating
    Units of Work
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  33. #QUESTION 🤔


    Have you ever heard about
    homoiconicity?

    View Slide

  34. (let [x 1]


    (inc x)) ;
    =
    >
    2
    HOMOICONICITY

    View Slide

  35. (let [x 1]


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


    (BINDS X TO THE VALUE 1)

    View Slide

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


    (inc x)) ;
    =
    >
    2
    HOMOICONICITY

    View Slide

  37. 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

  38. 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

  39. 🤯
    #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.”

    View Slide

  40. ↝ REACT ELEMENTS ARE JUST DATA


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

    View Slide

  41. #EXPERIMENT 💻


    #2 Pattern Matching in React

    View Slide

  42. PATTERN MATCHING

    View Slide

  43. /
    / .
    .
    .


    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

  44. 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

  45. 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

  46. const supportsSensor


    + REACT.SUSPENSE


    + REACT.LAZY()


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

    View Slide

  47. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  48. Fibers out
    there
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  49. ↝ 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

  50. Coroutines
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  51. View Slide

  52. #1 A GENERATOR (PRODUCER)
    THAT CAN ALSO CONSUME
    VALUES.
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  53. #1
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    ↝ JAVASCRIPT GENERATORS
    CAN CONSUME VALUES


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

    View Slide

  54. #2 A GENERATOR THAT CAN
    RESOLVE ASYNCHRONOUS
    VALUES, LIKE ASYNC/AWAIT.
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  55. #2
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    ↝ 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

  56. #3 A GENERATOR THAT CAN
    YIELD WITH A STACKFUL
    CONTINUATION
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  57. #3
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    ↝ "DEEP AWAIT"


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

    View Slide

  58. 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

  59. 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

  60. Coroutines &
    React
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  61. 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

  62. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  63. 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

  64. Coroutines &
    Concurrent
    React
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  65. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  66. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  67. 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

  68. #EXPERIMENT 💻


    #3 Building a coroutines-based
    scheduler

    View Slide

  69. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  70. View Slide

  71. 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

  72. 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

  73. 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

  74. DEEP DIVING ON CONCURRENT REACT

    View Slide

  75. 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

  76. 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

  77. DID WE JUST


    useTransition’ED? 🤔

    View Slide

  78. 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

  79. 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

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

    View Slide

  81. ↝ 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

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

    View Slide

  83. ↝ 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

  84. Coroutines out
    there
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  85. ↝ 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

  86. ↝ 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

  87. View Slide

  88. ↝ 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

  89. ↝ 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

  90. ↝ 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

  91. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  92. View Slide

  93. Continuations
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  94. CONTINUATIONS

    View Slide

  95. CONTINUATIONS
    ↝ A CONTINUATION IS A CONTROL FLOW PRIMITIVE.


    ↝ IT’S AN ABSTRACTION THAT REPRESENTS THE
    REMAINING STEPS IN A COMPUTATION.


    View Slide

  96. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  97. 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

  98. ↝ 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

  99. CONTINUATIONS ON THE WEB

    View Slide

  100. CONTINUATIONS ON THE WEB
    async function doWork() {


    while (true) {


    let hasMoreWork
    =
    doSomeWork();


    if (!hasMoreWork) {


    return;


    }


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


    continue;


    }


    await scheduler.yield();


    }


    }
    🤯

    View Slide

  101. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  102. Effect Handlers
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  103. ↝ EFFECTS ASK THE CALLING ENVIRONMENT TO
    HANDLE A PARTICULAR TASK


    ↝ WHEN AN EFFECT IS USED, THE NEAREST EFFECT
    HANDLER IS CALLED, WHICH ALLOWS YOU TO RUN
    CODE IN RESPONSE TO THE EFFECT AND RETURN
    SOME VALUE
    EFFECT HANDLERS
    🤯

    View Slide

  104. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  105. 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

  106. 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

  107. 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

  108. Effect
    handlers in
    React
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  109. #1
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    LAYOUT
    ALGORITHM

    View Slide

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

    View Slide

  111. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  112. #2
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    CONTEXT API
    DRAFTS

    View Slide

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

    View Slide

  114. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  115. #3
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    SIDE EFFECTS
    WITHIN A
    COMPONENT

    View Slide

  116. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  117. 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

  118. 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

  119. #4
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    HOOKS API
    DRAFTS

    View Slide

  120. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

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

    View Slide

  122. #5
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    SUSPENSE
    INTERNALS

    View Slide

  123. #QUESTION 🤔


    Have you ever built any suspense-
    ready API?

    View Slide

  124. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  125. 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

  126. 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

  127. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    Closing Notes

    View Slide

  128. #1 REACT FIBER WAS A REWRITE
    OF REACT FOCUSED ON
    GIVING MORE LOW-LEVEL
    CONTROL OVER PROGRAM
    EXECUTION
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  129. #1
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    ↝ 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

  130. #2
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    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

  131. #3
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    UNDERSTANDING THESE
    INTERNALS AND THEIR
    RATIONALES HELPS US
    IMPLEMENT OUR OWN
    ABSTRACTIONS


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

    View Slide

  132. View Slide

  133. #4 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
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  134. View Slide

  135. THIS IS THE EIGHT-YEARS-AGO-ME GIVING A
    TALK ABOUT IONIC AT AN IOS DEVELOPERS
    MEETUP TELLING THEM THAT ANGULAR WOULD
    BE THE FUTURE.

    View Slide

  136. #5
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
    DON’T ALWAYS TRUST ALL OF
    MY SPECULATIONS/FUTURE
    PREDICTIONS 🤷

    View Slide

  137. We’re hiring! 🗺


    Mostly in…
    🇺🇸🇲🇽🇦🇷🇺🇾🇪🇸🇨🇿🇮🇱🇮🇳

    View Slide

  138. 🤝 🇪🇸 🤗

    View Slide

  139. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  140. INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View Slide

  141. View Slide

  142. MATHEUS ALBUQUERQUE
    THAT’S ALL, FOLKS! THANKS!
    QUESTIONS?

    View Slide