High level breakdown of this commit:
* Add a enableSchedulingProfiling feature flag.
* Add functions that call User Timing APIs to a new SchedulingProfiler file. The file follows DebugTracing's structure.
* Add user timing marks to places where DebugTracing logs.
* Add user timing marks to most other places where @bvaughn's original draft DebugTracing branch marks.
* Tests added
* More context (and discussions with @bvaughn) available at our internal PR MLH-Fellowship#11 and issue MLH-Fellowship#5.
Similar to DebugTracing, we've only added scheduling profiling calls to the old reconciler fork.
Co-authored-by: Kartik Choudhary <kartik.c918@gmail.com>
Co-authored-by: Kartik Choudhary <kartikc.918@gmail.com>
Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>
* Initial currentLanePriority implementation
* Minor updates from review
* Fix typos and enable flag
* Fix feature flags and lint
* Fix simple event tests by switching to withSuspenseConfig
* Don't lower the priority of setPending in startTransition below InputContinuous
* Move currentUpdateLanePriority in commit root into the first effect block
* Refactor requestUpdateLane to log for priority mismatches
Also verifies that the update lane priority matches the scheduler lane priority before using it
* Fix four tests by adding ReactDOM.unstable_runWithPriority
* Fix partial hydration when using update lane priority
* Fix partial hydration when using update lane priority
* Rename feature flag and only log for now
* Move unstable_runWithPriority to ReactFiberReconciler
* Add unstable_runWithPriority to ReactNoopPersistent too
* Bug fixes and performance improvements
* Initial currentLanePriority implementation
* Minor updates from review
* Fix typos and enable flag
* Remove higherLanePriority from ReactDOMEventReplaying.js
* Change warning implementation and startTransition update lane priority
* Inject reconciler functions to avoid importing src/
* Fix feature flags and lint
* Fix simple event tests by switching to withSuspenseConfig
* Don't lower the priority of setPending in startTransition below InputContinuous
* Move currentUpdateLanePriority in commit root into the first effect block
* Refactor requestUpdateLane to log for priority mismatches
Also verifies that the update lane priority matches the scheduler lane priority before using it
* Fix four tests by adding ReactDOM.unstable_runWithPriority
* Fix partial hydration when using update lane priority
* Fix partial hydration when using update lane priority
* Rename feature flag and only log for now
* Move unstable_runWithPriority to ReactFiberReconciler
* Bug fixes and performance improvements
* Remove higherLanePriority from ReactDOMEventReplaying.js
* Change warning implementation and startTransition update lane priority
* Inject reconciler functions to avoid importing src/
* Fixes from bad rebase
The motivation for doing this is to make it impossible for additional
uses of pre-rendering to sneak into www without going through the
LegacyHidden abstraction. Since this feature was already disabled in
the new fork, this brings the two closer to parity.
The LegacyHidden abstraction itself still needs to opt into
pre-rendering somehow, so rather than totally disabling the feature, I
updated the `hidden` prop check to be obnoxiously specific. Before, you
could set it to any truthy value; now, you must set it to the string
"unstable-do-not-use-legacy-hidden".
The node will still be hidden in the DOM, since any truthy value will
cause the browser to apply a style of `display: none`.
I will have to update the LegacyHidden component in www to use the
obnoxious string prop. This doesn't block merge, though, since the
behavior is gated by a dynamic flag. I will update the component before
I enable the flag.
* Expose LegacyHidden type
I will use this internally at Facebook to migrate away from
<div hidden />. The end goal is to migrate to the Offscreen type, but
that has different semantics. This is an incremental step.
* Disable <div hidden /> API in new fork
Migrates to the unstable_LegacyHidden type instead. The old fork does
not support the new component type, so I updated the tests to use an
indirection that picks the correct API. I will remove this once the
LegacyHidden (and/or Offscreen) type has landed in both implementations.
* Add gated warning for `<div hidden />` API
Only exists so we can detect callers in www and migrate them to the new
API. Should not visible to anyone outside React Core team.
In the new reconciler, I made a change to how render phase updates
work. (By render phase updates, I mean when a component updates
another component during its render phase. Or when a class component
updates itself during the render phase. It does not include when
a hook updates its own component during the render phase. Those have
their own semantics. So really I mean anything triggers the "`setState`
in render" warning.)
The old behavior is to give the update the same "thread" (expiration
time) as whatever is currently rendering. So if you call `setState` on a
component that happens later in the same render, it will flush during
that render. Ideally, we want to remove the special case and treat them
as if they came from an interleaved event.
Regardless, this pattern is not officially supported. This behavior is
only a fallback. The flag only exists until we can roll out the
`setState` warnning, since existing code might accidentally rely on the
current behavior.
* Remove priority field from tracing
* Remove DebugTracing mode from new reconciler (temporarily)
* Run DebugTracing tests in the *other* variant so it's no on for new reconciler
* Filter certain DOM attributes (e.g. src, href) if their values are empty strings
This prevents e.g. <img src=""> from making an unnecessar HTTP request for certain browsers.
* Expanded warning recommendation
* Improved error message
* Further refined error message
* Add feature flag
* Split stack from current fiber
You can get stack from any fiber, not just current.
* Refactor description of component frames
These should use fiber tags for switching. This also puts the relevant code
behind DEV flags.
* We no longer expose StrictMode in component stacks
They're not super useful and will go away later anyway.
* Update tests
Context is no longer part of SSR stacks. This was already the case on the
client.
forwardRef no longer is wrapped on the stack. It's still in getComponentName
but it's probably just noise in stacks. Eventually we'll remove the wrapper
so it'll go away anyway. If we use native stack frames they won't have this
extra wrapper.
It also doesn't pick up displayName from the outer wrapper. We could maybe
transfer it but this will also be fixed by removing the wrapper.
* Forward displayName onto the inner function for forwardRef and memo in DEV
This allows them to show up in stack traces.
I'm not doing this for lazy because lazy is supposed to be called on the
consuming side so you shouldn't assign it a name on that end. Especially
not one that mutates the inner.
* Use multiple instances of the fake component
We mutate the inner component for its name so we need multiple copies.
* Enable new passive effect behavior for FB builds
Previously this behavior was controlled by GKs. This PR updates the flags to be enabled statically. It also enables the flags in the test builds.
In CI, we run our test suite against multiple build configurations. For
example, we run our tests in both dev and prod, and in both the
experimental and stable release channels. This is to prevent accidental
deviations in behavior between the different builds. If there's an
intentional deviation in behavior, the test author must account
for them.
However, we currently don't run tests against the www builds. That's
a problem, because it's common for features to land in www before they
land anywhere else, including the experimental release channel.
Typically we do this so we can gradually roll out the feature behind
a flag before deciding to enable it.
The way we test those features today is by mutating the
`shared/ReactFeatureFlags` module. There are a few downsides to this
approach, though. The flag is only overridden for the specific tests or
test suites where you apply the override. But usually what you want is
to run *all* tests with the flag enabled, to protect against unexpected
regressions.
Also, mutating the feature flags module only works when running the
tests against source, not against the final build artifacts, because the
ReactFeatureFlags module is inlined by the build script.
Instead, we should run the test suite against the www configuration,
just like we do for prod, experimental, and so on. I've added a new
command, `yarn test-www`. It automatically runs in CI.
Some of the www feature flags are dynamic; that is, they depend on
a runtime condition (i.e. a GK). These flags are imported from an
external module that lives in www. Those flags will be enabled for some
clients and disabled for others, so we should run the tests against
*both* modes.
So I've added a new global `__VARIANT__`, and a new test command `yarn
test-www-variant`. `__VARIANT__` is set to false by default; when
running `test-www-variant`, it's set to true.
If we were going for *really* comprehensive coverage, we would run the
tests against every possible configuration of feature flags: 2 ^
numberOfFlags total combinations. That's not practical, though, so
instead we only run against two combinations: once with `__VARIANT__`
set to `true`, and once with it set to `false`. We generally assume that
flags can be toggled independently, so in practice this should
be enough.
You can also refer to `__VARIANT__` in tests to detect which mode you're
running in. Or, you can import `shared/ReactFeatureFlags` and read the
specific flag you can about. However, we should stop mutating that
module going forward. Treat it as read-only.
In this commit, I have only setup the www tests to run against source.
I'll leave running against build for a follow up.
Many of our tests currently assume they run only in the default
configuration, and break when certain flags are toggled. Rather than fix
these all up front, I've hard-coded the relevant flags to the default
values. We can incrementally migrate those tests later.