* Add manual build fixtures
* Inject ReactDOM into ReactWithAddons from ReactWithAddons
We used to read ReactDOM as a global inside ReactAddonsDOMDependenciesUMDShim.
This didn't work in AMD environments such as RequireJS and SystemJS.
Instead, I changed it so that ReactDOM gets injected into ReactWithAddons by ReactDOM itself.
This way we don't have to try to require it (which wouldn't work because AMD doesn't handle circular dependencies well).
This means you have to load ReactDOM first before using ReactDOM-dependent addons, but this was already the case before.
This commit makes all build fixtures pass.
* Memoize ReactDOM to avoid going into require on every access
* Add Brunch fixture
* Inline requires to work around Brunch bug
See #8556 and https://github.com/brunch/brunch/issues/1591#issuecomment-270742503 for context.
This appears to be a Brunch bug but we can keep a temporary fix until the next major.
Moved ReactFiberClassComponent validateCallback() helper function into a standalone util used by both fiber and stack implementations. Validation now happens in ReactFiberUpdateQueue so that non-DOM renderers will also benefit from it.
Reverses the effect of batchedUpdates by resetting the current
batching context.
Does not affect nested updates, which are always deferred regardless
of whether they are inside a batch.
The DOM renderer assumes that resetAfterCommit is called after
prepareForCommit without any nested commits in between. That may not
be the case now that syncUpdates forces a nested update.
To address, this changes the type of prepareForCommit to return a value
which is later passed to resetAfterCommit.
Typically, a sync update is downgraded to Task priority if it's
scheduled within another batch of work, e.g. within a lifecycle like
componentDidMount. But syncUpdates should force sync updates to not
be downgraded to Task. This will cause performWork to be
called recursively.
Currently we assume that performWork is never called recursively.
Ideally that is the case. We shouldn't rely on recursion anywhere
in Fiber.
However, to support the use of syncUpdates as an opt-in to forced-
synchronous updates, we need the ability to call performWork
recursively.
At the beginning of performWork, the state of the scheduler is saved;
before exiting, that state is restored, so that the scheduler can
continue where it left off. I've decided to use local variables to stash
the previous state. We could also store them in a record and push it to
a stack, but this approach has the advantage of being isolated to
performWork.
This can only be caused by a bug in the renderer, but we should handle
it gracefully anyway.
Added a TODO to change capturedErrors and failedBoundaries so that they
are sets of instances (stateNodes) rather than fibers, to avoid having
to check the alternate. (This outside the scope of this PR.)
For legacy purposes. Only enabled in the DOM renderer. We can remove
this in a future release when we enable incremental-by-default.
This change is unobservable because syncUpdates actually schedules
Task updates when it is called from inside another batch. The correct
behavior is to recursively begin another batch of work. We will fix it
in a subsequent commit.
The finalizeInitialChildren HostConfig method now utilizes a boolean return type. Renderers can return true to indicate that custom effects should be processed at commit-time once host components have been mounted. This type of work is marked using the existing Update flag.
A new HostConfig method, commitMount, has been added as well for performing this type of work.
This change set is in support of the autoFocus prop.
* Push class context providers early
Previously we used to push them only after the instance was available. This caused issues in cases an error is thrown during componentWillMount().
In that case we never got to pushing the provider in the begin phase, but in complete phase the provider check returned true since the instance existed by that point. As a result we got mismatching context pops.
We solve the issue by making the context check independent of whether the instance actually exists. Instead we're checking the type itself.
This lets us push class context early. However there's another problem: we might not know the context value. If the instance is not yet created, we can't call getChildContext on it.
To fix this, we are introducing a way to replace current value on the stack, and a way to read the previous value. This also helps remove some branching and split the memoized from invalidated code paths.
* Add a now-passing test from #8604
Also rename another test to have a shorter name.
* Move isContextProvider() checks into push() and pop()
All uses of push() and pop() are guarded by it anyway.
This makes it more similar to how we use host context.
There is only one other place where isContextProvider() is used and that's legacy code needed for renderSubtree().
* Clarify why we read the previous context
* Use invariant instead of throwing an error
* Fix off-by-one in ReactFiberStack
* Manually keep track of the last parent context
The previous algorithm was flawed and worked by accident, as shown by the failing tests after an off-by-one was fixed.
The implementation of getPrevious() was incorrect because the context stack currently has no notion of a previous value per cursor.
Instead, we are caching the previous value directly in the ReactFiberContext in a local variable.
Additionally, we are using push() and pop() instead of adding a new replace() method.
ReactFiberStack is the new underlying stack used by ReactFiberContext and ReactFiberHostContext. The goal is to simplify the 2 context managers and to add more errors/dev-warnings when we pop unexpected.
This changeset currently causes a lot of tests to fail (as we are currently popping too many times and/or in the wrong order). I'm pushing this branch now to share with Sebastian as he is working on a related cleanup pass at beginWork.
* Add a failing test for recursion check
* Make requestIdleCallback() and requestAnimationFrame() shims async
They no longer need to be sync in tests because we already made DOM renderer sync by default.
This fixes a crash when testing incrementalness in DOM renderer itself.
* Style fix
* Fix lint
This was a bug because of the split between ClassComponent and IndeterminateComponent -- we didn't mark effects or push context when we come from an indeterminate component. Now they behave the same way.
The code is even clumsier than before but I'm pretty worried we'll screw these up in the future if we don't unify the paths.
Not many components exercise this path but Relay containers do so it's noticeable.
This is the same thing as the previous commit but with class, root and portal.
I noticed host and portal now already covers this case in their branches
since pushHostContainer is always at the top.
Since we only call bailout from within the host component branch now, we
can just move this to the branch where we already know that this is a
host component.
As part of this I noticed that we don't always push the host context so
I moved that to the beginning of the branch.
This is no longer needed. It is effectively covered by other branches
that tries to being merging the update queue which yields the same state
object as before if there is no work. That in turn bails out.
We can shortcut in the relevant paths if needed.
Now we only bail out once we've entered each branch.
This has some repetition with regard to hasContextChanged but I'm hoping
we can just get rid of all those branches at some point since they're
mostly for backwards compatibility right now.
The functional component branch is a bit special since it has sCU in it.
The class component branch actually already covers this in a bit convoluted
way.
I will next replicate this check in each other branch.
This consolidates the reset of context to one single place right before
any new work is started.
This place is burried in a bit of an awkward place but findNextUnitOfWork
happens right before any new work starts. That way we're guaranteed to have
an empty stack before we start anything new.
The benefit of this is that we don't have to rely .return being null when
entering beginWork but we also don't have to check it every time in the
hot path.