Skip to content
Branch: master
Commits on Dec 4, 2019
  1. Revert Rerender Error Check (#17519)

    sebmarkbage committed Dec 4, 2019
    * Add failing test
    * Revert "Move rerender error check to avoid global state"
    This reverts commit 3e77742.
Commits on Dec 3, 2019
  1. Don't group Idle/Offscreen work with other work (#17456)

    sebmarkbage committed Dec 3, 2019
    When we suspend we always try a lower level but we shouldn't try offscreen.
  2. Use fewer global variables in Hooks (#17480)

    sebmarkbage committed Dec 3, 2019
    * We don't need the global state for this
    * Move componentUpdateQueue and sideEffectTag out of global state
    * Move firstWorkInProgressHook off global state
    * Move remainingExpirationTime off global state
    * Reset fiber to its current state if it throws
    * Move rerender error check to avoid global state
    This means that it's harder to find it since it's not in the dispatch
    function's stack but we can add a DEV only one for that if we really
    need it. Alternatively, we can check it in against the renderUpdates queue.
    * Move next___Hook out of global state
    * Assert that currentlyRenderingFiber is always set
    When accessed, this should always be set. This could enforced by storing
    this on the dispatcher for example.
    * Add another test just to be safe
  3. Remove case that only exists for createBatch (#17506)

    sebmarkbage committed Dec 3, 2019
    The comment says this is only needed for createBatch().commit() which
    doesn't exist anymore.
  4. Adjust SuspenseList CPU bound heuristic (#17455)

    sebmarkbage committed Dec 3, 2019
    * Adjust SuspenseList CPU bound heuristic
    In SuspenseList we switch to rendering fallbacks (or stop rendering further
    rows in the case of tail="collapsed/hidden") if it takes more than 500ms
    to render the list. The limit of 500ms is similar to the train model and
    designed to be short enough to be in the not noticeable range.
    This works well if each row is small because we time the 500ms range well.
    However, if we have a few large rows then we're likely to exceed the limit
    by a lot. E.g. two 480ms rows hits almost a second instead of 500ms.
    This PR adjusts the heuristic to instead compute whether something has
    expired based on the render time of the last row. I.e. if we think rendering
    one more row would exceed the timeout, then we don't attempt.
    This still works well for small rows and bails earlier for large rows.
    The expiration is still based on the start of the list rather than the
    start of the render. It should probably be based on the start of the render
    but that's a bigger change and needs some thought.
    * Comment
Commits on Nov 17, 2019
  1. Update Fixtures to use new APIs (#17380)

    sebmarkbage committed Nov 17, 2019
    Also renamed unstable-async to concurrent
Commits on Nov 15, 2019
  1. Add Webpack as devDependency (#17379)

    sebmarkbage committed Nov 15, 2019
    This is now used by the Flight package so it needs to be installed as a
  2. [Flight] Move Flight DOM to a Webpack Specific Package (#17372)

    sebmarkbage committed Nov 15, 2019
    * Move Flight DOM to Webpack Specific Packagee
    We'll have Webpack specific coupling so we need to ensure that it can be
    versioned separately from various Webpack versions. We'll also have builds
    for other bundlers in the future.
    * Move to peerDep
    * Move DOM Flight Tests
    * Merge ReactFlightIntegration into ReactFlightDOM
    This was an integration test. We can add to it.
    * Fix fixture paths
Commits on Nov 6, 2019
  1. [Flight] Basic Streaming Suspense Support (#17285)

    sebmarkbage committed Nov 6, 2019
    * Return whether to keep flowing in Host config
    * Emit basic chunk based streaming in the Flight server
    When something suspends a new chunk is created.
    * Add reentrancy check
    The WHATWG API is designed to be pulled recursively.
    We should refactor to favor that approach.
    * Basic streaming Suspense support on the client
    * Add basic suspense in example
    * Add comment describing the protocol that the server generates
Commits on Nov 2, 2019
  1. [Flight] Move around the Server side a bit (#17251)

    sebmarkbage committed Nov 2, 2019
    * Rename ReactFlightStreamer -> ReactFlightServer
    * Unify Browser/Node stream tests into one file and use the client reader
    * Defer to the actual ReactDOM for HTML rendering for now
    This will need to use a variant of Fizz to do inline SSR in Flight.
    However, I don't want to build the whole impl right now but also don't
    want to exclude the use case yet. So I outsource it to the existing
    renderer. Ofc, this doesn't work with Suspense atm.
Commits on Nov 1, 2019
  1. [Flight] Add Client Infrastructure (#17234)

    sebmarkbage committed Nov 1, 2019
    * Change demo to server
    * Expose client in package.json
    * Reorganize tests
    We don't want unit tests but instead test how both server and clients work
    together. So this merges server/client test files.
    * Fill in the client implementation a bit
    * Use new client in fixture
    * Add Promise/Uint8Array to lint rule
    I'll probably end up deleting these deps later but they're here for now.
Commits on Oct 29, 2019
  1. Add Experimental Flight Infrastructure (#16398)

    sebmarkbage committed Oct 29, 2019
    * Add Flight Build and Unify HostFormat Config between Flight and Fizz
    * Add basic resolution of models
    * Add basic Flight fixture
    Demonstrates the streaming protocol.
    * Rename to flight-server to distinguish from the client parts
    * Add Flight Client package and entry point
    * Fix fixture
  2. Don't treat the last row in hidden as deleted if already mounted (#17206

    sebmarkbage committed Oct 29, 2019
    Already mounted rows that resuspend may be considered as part of a tail
    if they're at the end. However, for purposes of the tail="..." option
    they don't get deleted. We deal with that in cutOffTailIfNeeded.
    However, if they're also the first to suspend in the "hidden" case, we have
    a special case that deletes the actual rendered row. This needs to consider
    if that row was already mounted or things go wrong.
Commits on Oct 19, 2019
  1. SuspenseList support in DevTools (#17145)

    sebmarkbage committed Oct 19, 2019
    * SuspenseList support in DevTools
    This adds SuspenseList tags to DevTools so that the name properly shows
    It also switches to use the tag instead of Symbol type for Suspense
    components. We shouldn't rely on the type for any built-ins since that
    field will disappear from the fibers. How the Fibers get created is an
    implementation detail that can change e.g. with a compiler or if we
    use instanceof checks that are faster than symbol comparisons.
    * Add SuspenseList test to shell app
  2. Remove unstable_ prefix in various internal uses (#17146)

    sebmarkbage committed Oct 19, 2019
    * Rename unstable_createRoot in DevTools
    * Rename createSyncRoot in warning
Commits on Oct 17, 2019
  1. [SuspenseList] Store lastEffect before rendering (#17131)

    sebmarkbage committed Oct 17, 2019
    * Add a failing test for SuspenseList bug
    * Store lastEffect before rendering
    We can't reset the effect list to null because we don't rereconcile the
    children so we drop deletion effects if we do that.
    Instead we store the last effect as it was before we started rendering
    so we can go back to where it was when we reset it.
    We actually already do something like this when we delete the last row
    for the tail="hidden" mode so we had a field available for it already.
Commits on Oct 16, 2019
  1. Client render Suspense content if there's no boundary match (#16945)

    sebmarkbage authored and lunaruan committed Oct 16, 2019
    Without the enableSuspenseServerRenderer flag there will never be a boundary match. Also when it is enabled, there might not be a boundary match if something was conditionally rendered by mistake.
    With this PR it will now client render the content of a Suspense boundary in that case and issue a DEV only hydration warning. This is the only sound semantics for this case.
    Unfortunately, landing this will once again break #16938. It will be less bad though because at least it'll just work by client rendering the content instead of hydrating and issue a DEV only warning.
    However, we must land this before enabling the enableSuspenseServerRenderer flag since it does this anyway.
    I did notice that we special case fallback={undefined} due to our unfortunate semantics for that. So technically a workaround that works is actually setting the fallback to undefined on the server and during hydration. Then flip it on only after hydration. That could be a workaround if you want to be able to have a Suspense boundary work only after hydration for some reason.
    It's kind of unfortunate but at least those semantics are internally consistent. So I added a test for that.
  2. Change retry priority to "Never" for dehydrated boundaries (#17105)

    sebmarkbage committed Oct 16, 2019
    This changes the "default" retryTime to NoWork which schedules at Normal
    Dehydrated bouundaries normally hydrate at Never priority except when they
    retry where we accidentally increased them to Normal because Never was used
    as the default value. This changes it so NoWork is the default.
    Dehydrated boundaries however get initialized to Never as the default.
    Therefore they now hydrate as Never pri unless their priority gets
    increased by a forced rerender or selective hydration.
    This revealed that erroring at this Never priority can cause an infinite
    rerender. So I fixed that too.
Commits on Oct 14, 2019
  1. [SuspenseList] Fix bugs with dropped Promises (#17082)

    sebmarkbage committed Oct 14, 2019
    * Transfer any pending promises from inner boundary to list
    For non-hidden modes, this boundary should commit so this shouldn't be
    needed but the nested boundary can make a second pass which forces these
    to be recreated without resuspending. In this case, the outer list assumes
    that it can collect the inner promises to still rerender if needed.
    * Propagate suspense "context" change to nested SuspenseLists
    This means that we always rerender any nested SuspenseLists together.
    This bug looks similar to the previous one but is not based on the lack of
    retry but that the retry only happens on the outer boundary but the inner
    doesn't get a retry ping since it didn't know about its own promise after
    the second pass.
Commits on Oct 3, 2019
  1. [Selective Hydration] ReactDOM.unstable_scheduleHydration(domNode) (#…

    sebmarkbage committed Oct 3, 2019
    Adds an API to explicitly prioritize hydrating the path to a particular DOM node without relying on events to do it.
    The API uses the current scheduler priority to schedule it. For the same priority, the last one wins. This allows a similar effect as continuous events. This is useful for example to hydrate based on scroll position, or prioritize components that will upgrade to client-rendered-only content.
    I considered having an API that explicitly overrides the current target(s). However that makes it difficult to coordinate across components in an app.
    This just hydrates one target at a time but if it is blocked on I/O we could consider increasing priority of later targets too.
Commits on Oct 2, 2019
  1. [Selective Hydration] Prioritize the last continuous target (#16937)

    sebmarkbage committed Oct 2, 2019
    * Prioritize the last continuous target
    This ensures that the current focus target is always hydrated first.
    Slightly higher than the usual Never expiration time used for hydration.
    The priority increases with each new queued item so that the last always
    * Don't export the moving target
    It's not useful for comparison purposes anyway.
Commits on Sep 28, 2019
  1. Allow Suspense Mismatch on the Client to Silently Proceed (#16943)

    sebmarkbage committed Sep 28, 2019
    * Regression test: Suspense + hydration + legacy
    * Allow Suspense Mismatch on the Client to Silently Proceed
    This fixes but isn't actually the semantics that we want this case to have.
  2. Remove enableUserBlockingEvents flag (#16882)

    sebmarkbage committed Sep 28, 2019
    Seems like this worked out. We can clean up the flag now.
  3. [Selective Hydration] Increase priority for non-synchronous discrete …

    sebmarkbage committed Sep 28, 2019
    …events and retries (#16935)
    * Increase retryTime for increased priority dehydrated boundaries
    * Increaese the priority to user blocking for every next discrete boundary
Commits on Sep 25, 2019
  1. Selective Hydration (#16880)

    sebmarkbage committed Sep 25, 2019
    * Add Feature Flag for Selective Hydration
    * Enable Synchronous Hydration of Discrete Events
    * Resolve cyclic dependency
  2. Include tag in begin/complete invariant (#16881)

    sebmarkbage committed Sep 25, 2019
  3. These flags are hard coded in our internal config (#16883)

    sebmarkbage committed Sep 25, 2019
    By hard coding them here they can get properly DCE and don't have to be
    sent to users. The internal config should only have dynamic flags.
Commits on Sep 23, 2019
  1. Event Replaying (#16725)

    sebmarkbage committed Sep 23, 2019
    * Add Event Replaying Infra
    * Wire up Roots and Suspense boundaries, to retry events, after they commit
    * Replay discrete events in order in a separate scheduler callback
    * Add continuous events
    These events only replay their last target if the target is not yet
    hydrated. That way we don't have to wait for a previously hovered
    boundary before invoking the current target.
    * Enable tests from before
    These tests were written with replaying in mind and now we can properly
    enable them.
    * Unify replaying and dispatching
    * Mark system flags as a replay and pass to legacy events
    That way we can check if this is a replay and therefore needs a special
    case. One such special case is "mouseover" where we check the
    * Eagerly listen to all replayable events
    To minimize breakages in a minor, I only do this for the new root APIs
    since replaying only matters there anyway. Only if hydrating.
    For Flare, I have to attach all active listeners since the current
    system has one DOM listener for each. In a follow up I plan on optimizing
    that by only attaching one if there's at least one active listener
    which would allow us to start with only passive and then upgrade.
    * Desperate attempt to save bytese
    * Add test for mouseover replaying
    We need to check if the "relatedTarget" is mounted due to how the old
    event system dispatches from the "out" event.
    * Fix for nested boundaries and suspense in root container
    This is a follow up to #16673 which didn't have a test because it wasn't
    observable yet. This shows that it had a bug.
Commits on Sep 19, 2019
  1. Exclude react-dom when flow checking other builds (#16737)

    sebmarkbage committed Sep 19, 2019
    This is because the HostConfig can't be guaranteed to be consistent with
    other code such as code that touches the DOM directly.
    Ideally we'd have a more systemic solution to this since it will pop
    up for other packages later too.
Commits on Sep 11, 2019
  1. Mark root as already hydrated after committing (#16739)

    sebmarkbage committed Sep 11, 2019
    * Mark root as already hydrated after committing
    * Remove current/child check for hydration and rely on the root flag instead
  2. Handle SuspenseListComponent getting retried (#16745)

    sebmarkbage committed Sep 11, 2019
    This happens for example when a deleted boundary transfers its pending
    promises to the list so that the list can be retried.
    This wasn't caught by unit tests because this flag wasn't on in those
Commits on Sep 9, 2019
  1. Let's schedule the passive effects even earlier (#16714)

    sebmarkbage committed Sep 9, 2019
    It turns out I needed to schedule mine in the mutation phase and there
    are also clean up life-cycles there.
Commits on Sep 5, 2019
  1. Check for Suspense boundary in a root Container (#16673)

    sebmarkbage committed Sep 5, 2019
    If we find a Container that might mean that we're on a node that is inside
    a Suspense boundary that is directly inside the Container root.
    Imagine the div is a Container and the span is a dehydrated instance:
      <span />
    There's no way to tests this yet since I'm not actually utilizing
    the return value yet.
    The solution is to just use the same path to check for a Suspense boundary
    as if we find a parent instance.
  2. [Partial Hydration] Don't invoke listeners on parent of dehydrated ev…

    sebmarkbage committed Sep 5, 2019
    …ent target (#16591)
    * Don't invoke listeners on parent of dehydrated event target
    * Move Suspense boundary check to getClosestInstanceFromNode
    Now getClosestInstanceFromNode can return either a host component,
    host text component or suspense component when the suspense
    component is dehydrated.
    We then use that to ignore events on a suspense component.
    * Attach the HostRoot fiber to the DOM container
    This lets us detect if an event happens on this root's subtree before it
    has rendered something.
    * Add todo
    The approach of checking isFiberMounted answers if we might be in an
    in-progress hydration but it doesn't answer which root or boundary
    might be in-progress so we don't know what to wait for.
    This needs some refactoring.
    * Refactor isFiberMountedImpl to getNearestMountedFiber
    We'll need the nearest boundary for event replaying so this prepares for
    This surfaced an issue that we attach Hydrating tag on the root but normally
    this (and Placement) is attached on the child. This surfaced an issue
    that this can lead to both Placement and Hydrating effects which is not
    supported so we need to ensure that we only ever use one or the other.
    * Add todo for bug I spotted
    * Cache tags
    * Check the ContainerInstanceKey before the InstanceKey
    The container is inside the instance, so we must find it before the
    instance, since otherwise we'll miss it.
You can’t perform that action at this time.