(Except transitions and retries.)
The idea is that the only priorities that benefit from multiple parallel
updates are the ones that might suspend: transitions and retries. All
other priorities, including the ones that are interruptible like
Continuous and Idle, don't need multiple lanes because it's better to
batch everything together.
We don't always keep the reconciler forks in sync (otherwise it we
wouldn't have forked it) but during periods when they are meant to be in
sync, we use this job to confirm there are no differences.
* Parallelize Flow in CI
We added more host configs recently, and we run all the checks in
sequence, so sometimes Flow ends up being the slowest CI job.
This splits the job across multiple processes.
* Fix environment variable typo
Co-authored-by: Ricky <rickhanlonii@gmail.com>
Co-authored-by: Ricky <rickhanlonii@gmail.com>
The only difference between default updates and transition updates is
that default updates do not support suspended refreshes — they will
instantly display a fallback.
Co-authored-by: Rick Hanlon <rickhanlonii@gmail.com>
* Apply #20778 to new fork, too
* Fix tests that use runWithPriority
Where possible, I tried to rewrite in terms of an idiomatic API.
For DOM tests, we should be dispatching an event with the desired
priority level.
For Idle updates (very unstable feature), probably need an unstable
API like ReactDOM.unstable_IdleUpdates.
Some of these fixes are not great, but we can replace them once we've
landed the more of our planned changes to the layering between
Scheduler, the reconciler, and the renderer.
* Convert some old discrete tests to Hooks
I'm planning to copy paste so why not update them anyway.
* Copy paste discrete tests into another file
These are still using React events. I'll change that next.
* Convert the test to use native events
* Add the feature flag
* Add a host config method
* Wire it up to the work loop
* Export constants for third-party renderers
* Document for third-party renderers
Now that interleaved updates are added to a special queue, we no longer
need to shift them into their own lane. We can add to a lane that's
already in the middle of rendering without risk of tearing.
See #20615 for more background.
I've only changed this in the new fork, and only behind the
enableTransitionEntanglements flag.
Most of this commit involves updating tests. The "shift-to-a-new" lane
trick was intentionally used in a handful of tests where two or more
updates need to be scheduled in different lanes. Most of these tests
were written before `startTransition` existed, and all of them were
written before transitions were assigned arbitrary lanes.
So I ported these tests to use `startTransition` instead, which is the
idiomatic way to mark an update as parallel.
I didn't change the old fork at all. Writing these tests in such a way
that they also pass in the old fork actually revealed a few flaws in the
current implementation regarding interrupting a suspended refresh
transition early, which is a good reminder that we should be writing our
tests using idiomatic patterns as much as we possibly can.
* Land enableTransitionEntanglement changes
Leaving the flag though because I plan to reuse it for additional,
similar changes.
* Assign different lanes to consecutive transitions
Currently we always assign the same lane to all transitions. This means
if there are two pending transitions at the same time, neither
transition can finish until both can finish, even if they affect
completely separate parts of the UI.
The new approach is to assign a different lane to each consecutive
transition, by shifting the bit to the right each time. When we reach
the end of the bit range, we cycle back to the first bit. In practice,
this should mean that all transitions get their own dedicated lane,
unless we have more pending transitions than lanes, which should
be rare.
We retain our existing behavior of assigning the same lane to all
transitions within the same event. This is achieved by caching the first
lane assigned to a transition, then re-using that one until the next
React task, by which point the event must have finished. This preserves
the guarantee that all transition updates that result from a single
event will be consistent.
Because we have access to the artifacts in CI, we can read bundle sizes
directly from the filesystem, instead of the JSON files emitted by our
custom Rollup plugin.
This gives us some flexibility if we ever have artifacts that aren't
generated by Rollup, or if we rewrite our build script.
Personally, I also prefer to see the whole file path, instead of just
the name, because some of our names are repeated.
My immediate motivation, though, is because it gives us a way to merge
the separate "experimental" and "stable" size results. Instead
everything is reported in a single table and disambiguated by path.
I also added a section at the top that always displays the size impact
to certain critical bundles — right now, that's the React DOM production
bundles for each release channel. This section will also include any
size changes larger than 2%.
Below that is a section that is collapsed by default and includes all
size changes larger than 0.2%.
PR #20728 added a command to initiate a prerelease using CI, but it left
the publish job unimplemented. This fills in the publish job.
Uses an npm automation token for authorization, which bypasses the need
for a one-time password. The token is configured via CircleCI's
environment variable panel.
Currently, it will always publish the head of the main branch. If the
head has already been published, it will exit gracefully.
It does not yet support publishing arbitrary commits, though we could
easily add that. I don't know how important that use case is, because
for PR branches, you can use CodeSandbox CI instead. Or as a last
resort, run the publish script locally.
Always publishing from main is nice because it further incentivizes us
to keep main in a releasable state. It also takes the guesswork out of
publishing a prerelease that's in a broken state: as long as we don't
merge broken PRs, we're fine.
```
yarn publish-prereleases
```
Script to trigger a CircleCI workflow that publishes preleases.
**The CI workflow doesn't actually publish yet; it just runs and logs
its inputs.**
GitHub's status API is super flaky. Sometimes it reports a job as
"pending" even after it completes in CircleCI. If it's still pending
when we time out, return the build ID anyway. TODO: The location of the
retry loop is a bit weird. We should probably combine this function with
the one that downloads the artifacts, and wrap the retry loop around the
whole thing.
Adds a new CircleCI workflow, which I will use to publish prereleases
(`next` and `experimental`) for a given commit.
The CircleCI API doesn't yet support triggering a specific workflow, but
it does support triggering a pipeline. So as a workaround you can
triggger the entire pipeline and use parameters to disable everything
except the workflow you want. CircleCI recommends this workaround here:
https://support.circleci.com/hc/en-us/articles/360050351292-How-to-trigger-a-workflow-via-CircleCI-API-v2-
Eventually we can set this workflow to trigger on a cron schedule (once
per week, for example).
* build-combined: Fix bundle sizes path
* Output COMMIT_SHA in build directory
Alternative to parsing an arbitrary package's version number, or
its `build-info.json`.
* Remove CircleCI environment variable requirement
I think this only reason we needed this was to support passing any
job id to `--build`, instead of requiring the `process_artifacts` job.
And to do that you needed to use the workflows API endpoint, which
requires an API token.
But now that the `--commit` argument exists and automatically finds the
correct job id, we can just use that.
* Add CI job that gets base artifacts
Uses download-experimental script and places the base artifacts into
a top-level folder.
* Migrate sizebot to combined workflow
Replaces the two separate sizebot jobs (one for each channel, stable and
experimental) with a single combined job that outputs size information
for all bundles in a single GitHub comment.
I didn't attempt to simplify the output at all, but we should. I think
what I would do is remove our custom Rollup sizes plugin, and read the
sizes from the filesystem instead. We would lose some information about
the build configuration used to generate each artifact, but that can be
inferred from the filepath. For example, the filepath
`fb-www/ReactDOM-dev.classic.js` already tells us everything we need to
know about the artifact. Leaving this for a follow up.
* Move GitHub status check inside retry loop
The download script will poll the CircleCI endpoint until the build job
is complete; it should also poll the GitHub status endpoint if the
build job hasn't been spawned yet.
* Only run get_base_build on main branch
Also update instructions to match recent script changes.
Also add reproducible commit SHA to post download instructions to support publishing the Firefox DevTools extension.
PR #20717 accidentally broke the `--commit` parameter because the
script errors if you provide both a `--build` and a `--commit`.
I solved by removing the validation error. When there's a conflict, it
will choose the --`build`.
(Although maybe we should `--build` entirely and always uses `--commit`.
I think `--commit` is a sufficient replacement.)
* Retry loop should not start over from beginning
When the otp times out, we should not retry the packages that were
already successfully published. We should pick up where we left off.
* Don't crash if build-info.json doesn't exist
The "print follow up instructions" step crashes if build-info.json is
not found. The new build workflow doesn't include those yet (might not
need to) and since the instructions that depend on it only affect
semver (latest) releases, I've moved the code to that branch. Will
follow up with a proper fix, either by adding back a build-info.json
file or removing that dependency and reading the commit some other way.
* Concurrent Mode test for uMS render mutation
Same test as the one added in #20665, but for Concurrent Mode.
* Use double render to detect render phase mutation
PR #20665 added a mechanism to detect when a `useMutableSource` source
is mutated during the render phase. It relies on the fact that we double
invoke components that error during development using
`invokeGuardedCallback`. If the version in the double render doesn't
match the first, that indicates there must have been a mutation during
render.
At first I thought it worked by detecting inside the *other* double
render, the one we do for Strict Mode. It turns out that while it does
warn then, the warning is suppressed, because we suppress all console
methods that occur during the Strict Mode double render. So it's really
the `invokeGuardedCallback` one that makes it work.
Anyway, let's set that aside that issue for a second. I realized during
review that errors that occur during the Strict Mode double render
reveal a useful property: A pure component will never throw during the
double render, because if it were pure, it would have also thrown during
the first render... in which case it wouldn't have double rendered! This
is true of all such errors, not just the one thrown by
`useMutableSource`.
Given this, we can simplify the `useMutableSource` mutation detection
mechanism. Instead of tracking and comparing the source's version, we
can instead check if we're inside a double render when the error is
thrown.
To get around the console suppression issue, I changed the warning to an
error. It errors regardless, in both dev and prod, so it doesn't have
semantic implications.
However, because of the paradox I described above, we arguably
_shouldn't_ throw an error in development, since we know that error
won't happen in production, because prod doesn't double render. (It's
still a tearing bug, but that doesn't mean the component will actually
throw.) I considered that, but that requires a larger conversation about
how to handle errors that we know are only possible in development. I
think we should probably be suppressing *all* errors (with a warning)
that occur during a double render.
If build job is still pending, the script will continously poll until
it reaches the retry limit.
I've set the limit at 10 minutes, since our CI pipeline almost always
finishes before that.
Alternative to `--build`. Uses same logic as sizebot and www
sync script.
Immediate motivation is I want sizebot to use the
`download-experimental-build` command in CI. Will do that next.