Skip to content
Branch: master
Commits on Jan 17, 2020
  1. Remove renderPhaseUpdates Map (#17625)

    acdlite committed Jan 17, 2020
    * Remove renderPhaseUpdates Map
    Follow up to #17484, which was reverted due to a bug found in www.
    * Failing test: Dropped updates
    When resetting render phase updates after a throw, we should only clear
    the pending queue of hooks that were already processed.
    * Fix non-render-phase updates being dropped
    Detects if a queue has been processed by whether the hook was cloned.
    If we change the implementation to an array instead of a list, we'll
    need some other mechanism to determine whether the hook was processed.
    * Regression test: startTransition in render phase
    useTransition uses the state hook as part of its implementation, so we
    need to fork it in the dispatcher used for re-renders, too.
Commits on Dec 11, 2019
  1. Initialize update queue object on mount (#17560)

    acdlite committed Dec 11, 2019
    * Refactor Update Queues to Fix Rebasing Bug
    Fixes a bug related to rebasing updates. Once an update has committed,
    it should never un-commit, even if interrupted by a higher priority
    update. The fix includes a refactor of how update queues work.
    This commit is a combination of two PRs:
    - #17483 by @sebmarkbage refactors the hook update queue
    - #17510 by @acdlite refactors the class and root update queue
    Landing one without the other would cause state updates to sometimes be
    inconsistent across components, so I've combined them into a single
    commit in case they need to be reverted.
    Co-authored-by: Sebastian Markbåge <>
    Co-authored-by: Andrew Clark <>
    * Initialize update queue object on mount
    Instead of lazily initializing update queue objects on the first update,
    class and host root queues are created on mount. This simplifies the
    logic for appending new updates and matches what we do for hooks.
Commits on Dec 9, 2019
  1. Revert Update Queue Refactor

    acdlite committed Dec 9, 2019
    Reverts b617db3.
    Found some bugs when attempting to land in www. Reverting to fix master.
    I'll land again *after* the change successfully land downstream.
  2. Refactor Update Queues to Fix Rebasing Bug

    acdlite and sebmarkbage committed Dec 9, 2019
    Fixes a bug related to rebasing updates. Once an update has committed,
    it should never un-commit, even if interrupted by a higher priority
    update. The fix includes a refactor of how update queues work.
    This commit is a combination of two PRs:
    - #17483 by @sebmarkbage refactors the hook update queue
    - #17510 by @acdlite refactors the class and root update queue
    Landing one without the other would cause state updates to sometimes be
    inconsistent across components, so I've combined them into a single
    commit in case they need to be reverted.
    Co-authored-by: Sebastian Markbåge <>
    Co-authored-by: Andrew Clark <>
Commits on Nov 21, 2019
  1. Update release script URL (#17428)

    acdlite committed Nov 21, 2019
    CircleCI API endpoint changed
Commits on Nov 17, 2019
  1. Forgot to mark test as experimental (#17391)

    acdlite committed Nov 17, 2019
Commits on Nov 15, 2019
  1. [Bugfix] Pending state is always user-blocking (#17382)

    acdlite committed Nov 15, 2019
    Fixes a bug where `isPending` is only set to `true` if `startTransition`
    is called from inside an input event. That's usually the case, but
    not always.
    Now it works regardless of where you call it.
Commits on Nov 12, 2019
  1. [Bugfix] Passive effects triggered by synchronous renders in a multi-…

    acdlite committed Nov 12, 2019
    …root app (#17347)
    * Regression test: Effects dropped across roots
    See #17066
    * [Bugfix] Passive effects loop
    The bug
    In a multi-root app, certain passive effects (`useEffect`) are never
    fired. See #17066.
    The underlying problem
    The implicit contract of `flushPassiveEffects` is that, right after
    calling it, there should be no pending passive effects. In the normal
    case, in concurrent mode, this is true. But the current implementation
    fails to account for the case where a passive effect schedules
    synchronous work, which in turn schedules additional passive effects.
    This led to `rootWithPendingPassiveEffects` being overwritten in the
    commit phase, because an assignment that assumed it was replacing null
    was actually replacing a reference to another root, which has the
    consequence of dropping passive effects on that root.
    The fix
    The fix I've chosen here is, at the beginning of the commit phase, keep
    flushing passive effects in a loop until there are no more.
    This doesn't not change the "public" implementation of
    `flushPassiveEffects`, though it arguably should work this way, too. I
    say "public" because it's only used by implementation layers on top of
    React which we control: mainly, the legacy version of `act` that does
    not use the mock Scheduler build. So there's probably still a bug
    in that `act` implementation.
    I will address `act` in a follow-up. The ideal solution is to replace
    the legacy `act` with one implemented directly in the renderer, using a
    special testing-only build of React DOM. Since that requires a breaking
    change, we'll need an interim solution. We could make the "public" `act`
    recursively flush effects in a loop, as I've done for the commit phase.
    However, I think a better solution is to stop automatically flushing the
    synchronous update queue at the end of `flushPassiveEffects`, and
    instead require the caller to explicitly call `flushSyncUpdateQueue` (or
    the equivalent) if needed. This follows the same pattern we use
    internally in the work loop, which is designed to avoid factoring
    hazards like the one that resulted in this bug.
Commits on Nov 4, 2019
  1. Remove `debugRenderPhaseSideEffects` flag (#17270)

    acdlite committed Nov 4, 2019
    There are two similar flags, `debugRenderPhaseSideEffects` and
    `debugRenderPhaseSideEffectsForStrictMode`. The strict mode one is the
    only one that is actually used. I think originally the theory is that
    we would one day turn it on for all components, even outside strict
    mode. But what we'll do instead is migrate everyone to strict mode.
    The only place `debugRenderPhaseSideEffects` was being used was in
    an internal test file. I rewrote those tests to use public APIs.
Commits on Nov 1, 2019
  1. [Scheduler] Delete old rAF implementation (#17252)

    acdlite committed Nov 1, 2019
    We've been using the message loop version for a while. Time to delete.
  2. Codemod tests to `it.experimental` (#17243)

    acdlite committed Nov 1, 2019
    `it.experimental` marks that a test only works in Experimental builds.
    It also asserts that a test does *not* work in the stable builds. The
    main benefit is that we're less likely to accidentally expose an
    experimental API before we intend. It also forces us to un- mark an
    experimental test once it become stable.
Commits on Oct 22, 2019
  1. Changelog for 16.11.0

    acdlite committed Oct 22, 2019
Commits on Oct 21, 2019
  1. Read current time without marking event start time (#17160)

    acdlite committed Oct 21, 2019
    * Failing test: DevTools hook freezes timeline
    The DevTools hook calls `requestCurrentTime` after the commit phase has
    ended, which has the accidnental consequence of freezing the start
    time for subsequent updates. If enough time goes by, the next update
    will instantly expire.
    I'll push a fix in the next commit.
    * Read current time without marking event start time
    `requestCurrentTime` is only meant to be used for updates, because
    subsequent calls within the same event will receive the same time.
    Messing this up has bad consequences.
    I renamed it to `requestCurrentTimeForUpdate` and created a new
    function that returns the current time without the batching heuristic,
    called `getCurrentTime`.
    Swapping `requestCurrentTime` for `getCurrentTime` in the DevTools
    hook fixes the regression test added in the previous commit.
Commits on Oct 19, 2019
  1. Experimental test helper: `it.experimental` (#17149)

    acdlite committed Oct 19, 2019
    Special version of Jest's `it` for experimental tests. Tests marked as
    experimental will run **both** stable and experimental modes. In
    experimental mode, they work the same as the normal Jest methods. In
    stable mode, they are **expected to fail**. This means we can detect
    when a test previously marked as experimental can be un-marked when the
    feature becomes stable. It also reduces the chances that we accidentally
    add experimental APIs to the stable builds before we intend.
    I added corresponding methods for the focus and skip APIs:
    - `fit` -> `fit.experimental`
    - `it.only` -> `it.only.experimental` or `it.experimental.only`
    - `xit` -> `xit.experimental`
    - `it.skip` -> `it.skip.experimental` or `it.experimental.skip`
    Since `it` is an alias of `test`, `test.experimental` works, too.
  2. Build script should default to experimental (#17144)

    acdlite committed Oct 19, 2019
    `yarn build` defaults to building in experimental mode. To opt-out, set
    the `RELEASE_CHANNEL` environment variable to `stable`. This is the same
    as what we do when running tests via `yarn test`, to make local
    development easier.
Commits on Oct 18, 2019
  1. Add experimental instructions to release README (#17143)

    acdlite committed Oct 18, 2019
  2. Lint experimental build artifacts (#17141)

    acdlite committed Oct 18, 2019
    Adds `lint_build` job to the experimental workflow
  3. Don't build non-experimental www bundles (#17139)

    acdlite committed Oct 18, 2019
    Reduces the likelihood we'll accidentally sync the wrong ones.
  4. Move SuspenseList to experimental package (#17130)

    acdlite committed Oct 18, 2019
    Also moves `withSuspenseConfig`
Commits on Oct 17, 2019
  1. Remove prefixed concurrent APIs from www build (#17108)

    acdlite committed Oct 17, 2019
    The downstream callers have been updated, so we can remove these.
Commits on Oct 16, 2019
  1. unstable_createRoot -> createRoot in test (#17107)

    acdlite committed Oct 16, 2019
    Fixes test added in #17105, which was based on an earler commit than the
    one that removed the `unstable_` prefix from `createRoot`.
  2. Separate sizebot for experimental builds (#17100)

    acdlite committed Oct 16, 2019
    Configures the sizebot to leave a second comment that tracks the
    experimental build artifacts.
Commits on Oct 15, 2019
  1. Temporary patch www fork with prefixed APIs (#17103)

    acdlite committed Oct 15, 2019
    I'm doing this here instead of in the downstream repo so that if the
    sync diff gets reverted, it doesn't revert this, too.
    Once the sync has landed, and the callers are updated in www, I will
    remove this.
  2. Enable concurrent APIs in all experimental forks (#17102)

    acdlite committed Oct 15, 2019
    Forgot to update the flags in the forked modules.
  3. Remove concurrent apis from stable (#17088)

    acdlite committed Oct 15, 2019
    * Tests run in experimental mode by default
    For local development, you usually want experiments enabled. Unless
    the release channel is set with an environment variable, tests will
    run with __EXPERIMENTAL__ set to `true`.
    * Remove concurrent APIs from stable builds
    Those who want to try concurrent mode should use the experimental
    builds instead.
    I've left the `unstable_` prefixed APIs in the Facebook build so we
    can continue experimenting with them internally without blessing them
    for widespread use.
    * Turn on SSR flags in experimental build
    * Remove prefixed concurrent APIs from www build
    Instead we'll use the experimental builds when syncing to www.
    * Remove "canary" from internal React version string
Commits on Oct 14, 2019
  1. Update release scripts to support experimental releases (#17086)

    acdlite committed Oct 14, 2019
    * Download correct artifacts for release channel
    Experimental builds should pull artifacts from the
    `process_artifacts_experimental` job.
    I think instead of two separate CI workflows, a better approach might
    be to build stable artifacts to the `build` directory and the
    experimental artifacts to a `build_experimental` directory, and
    generate both within the same workflow. This would take some work since
    lots of things assume the output directory is `build`, but something
    to consider in the future.
    * Prevent experimental promotion to stable
    Adds a check to the `prepare-stable` script to prevent experimental
    builds from being published using stable semver versions.
  2. Set up experimental builds (#17071)

    acdlite committed Oct 14, 2019
    * Don't bother including `unstable_` in error
    The method names don't get stripped out of the production bundles
    because they are passed as arguments to the error decoder.
    Let's just always use the unprefixed APIs in the messages.
    * Set up experimental builds
    The experimental builds are packaged exactly like builds in the stable
    release channel: same file structure, entry points, and npm package
    names. The goal is to match what will eventually be released in stable
    as closely as possible, but with additional features turned on.
    Versioning and Releasing
    The experimental builds will be published to the same registry and
    package names as the stable ones. However, they will be versioned using
    a separate scheme. Instead of semver versions, experimental releases
    will receive arbitrary version strings based on their content hashes.
    The motivation is to thwart attempts to use a version range to match
    against future experimental releases. The only way to install or depend
    on an experimental release is to refer to the specific version number.
    I did not use the existing feature flag infra to configure the
    experimental builds. The reason is because feature flags are designed
    to configure a single package. They're not designed to generate multiple
    forks of the same package; for each set of feature flags, you must
    create a separate package configuration.
    Instead, I've added a new build dimension called the **release
    channel**. By default, builds use the **stable** channel. There's
    also an **experimental** release channel. We have the option to add more
    in the future.
    There are now two dimensions per artifact: build type (production,
    development, or profiling), and release channel (stable or
    experimental). These are separate dimensions because they are
    combinatorial: there are stable and experimental production builds,
    stable and experimental developmenet builds, and so on.
    You can add something to an experimental build by gating on
    `__EXPERIMENTAL__`, similar to how we use `__DEV__`. Anything inside
    these branches will be excluded from the stable builds.
    This gives us a low effort way to add experimental behavior in any
    package without setting up feature flags or configuring a new package.
Commits on Oct 11, 2019
  1. Pass prod error messages directly to constructor (#17063)

    acdlite committed Oct 11, 2019
    * Remove "Invariant Violation" from dev errors
    When I made the change to compile `invariant` to throw expressions, I
    left a small runtime to set the error's `name` property to "Invariant
    Violation" to maintain the existing behavior.
    I think we can remove it. The argument for keeping it is to preserve
    continuity in error logs, but this only affects development errors,
    anyway: production error messages are replaced with error codes.
    * Pass prod error messages directly to constructor
    Updates the `invariant` transform to pass an error message string
    directly to the Error constructor, instead of mutating the
    message property.
    Turns this code:
    invariant(condition, 'A %s message that contains %s', adj, noun);
    into this:
    if (!condition) {
      throw Error(
          ? `A ${adj} message that contains ${noun}`
          : formatProdErrorMessage(ERR_CODE, adj, noun)
Commits on Oct 7, 2019
  1. Remove unused export

    acdlite committed Oct 7, 2019
    Meant to do this in e4b21be but neglected to `git add` the changes.
  2. Remove dormant createBatch experiment (#17035)

    acdlite committed Oct 7, 2019
    * Remove dormant createBatch experiment
    In a hybrid React app with multiple roots, `createBatch` is used to
    coordinate an update to a root with its imperative container.
    We've pivoted away from multi-root, hybrid React apps for now to focus
    on single root apps.
    This PR removes the API from the codebase. It's possible we'll add back
    some version of this feature in the future.
    * Remove unused export
  3. [Scheduler Profiler] Use microsecond precision (#17010)

    acdlite committed Oct 7, 2019
    The `` returns a timestamp in milliseconds as a float.
    The browser has the option to adjust the precision of the float, but
    it's usually more precise than a millisecond. However, this precision
    is lost when the timestamp is logged by the Scheduler profiler, because
    we store the numbers in an Int32Array.
    This change multiplies the millisecond float value by 1000, giving us
    three more degrees of precision.
Commits on Oct 3, 2019
  1. Changelog for v16.10.2

    acdlite committed Oct 3, 2019
  2. Update local version numbers for 16.10.2 release

    acdlite committed Oct 3, 2019
Commits on Sep 30, 2019
  1. Remove IIFE wrappers from dev invariant checks (#16963)

    acdlite committed Sep 30, 2019
    The error transform works by replacing calls to `invariant` with
    an `if` statement.
    Since we're replacing a call expression with a statement, Babel wraps
    the new statement in an immediately-invoked function expression (IIFE).
    This wrapper is unnecessary in practice because our `invariant` calls
    are always part of their own expression statement.
    In the production bundle, the function wrappers are removed by Closure.
    But they remain in the development bundles.
    This commit updates the transform to confirm that an `invariant` call
    expression's parent node is an expression statement. (If not, it throws
    a transform error.)
    Then, it replaces the expression statement instead of the expression
    itself, effectively removing the extraneous IIFE wrapper.
You can’t perform that action at this time.