This strategy finds the current fiber. It traverses back up to the root if
the two trees are completely separate and determines which one is current.
If the two trees converge anywhere along the way, we assume that is the
current tree. We find the current child by searching the converged child
set.
This could fail if there's any way for both return pointers to point
backwards to the work in progress. I don't think there is but I could be
wrong.
This may also fail on coroutines where we have reparenting situations.
This was supposed to fix an issue in refs-test but instead it revealed that
this strategy is broken.
The problem is that Placement effect is not sufficient when the insertion
is completed since the effect flag is reset then and the previous tree
has no effects in it to indicate that this is the wrong tree.
I came up with a contrived case of where nested controlled events could
fire within the same batch - but on different targets.
I think we came to the conclusion that controlled values typically cannot
use preventDefault so it is ok that they don't flush until after the event
has finished. So therefore we accumulate a queue of all the nested targets
within a batch and then restore state on all of them.
I'm still skeptical that this is the correct way to do controlled values.
The reason we have to do them in a single event loop is because when you
type, the sequence of values that get accepted or not can matter. I wonder
if there is a scenario we can come up with where you can fire multiple
inner events in an event loop and end up with batching causing problems.
This effectively just reimplements asap again but with no allocations for
a single target and no closure allocations.
* Use explicit pass for restoring controlled state instead of asap
This gets rid of the first class ReactUpdates.asap scheduling. Instead of
scheduling a first class function to invoke later, I introduce an explicit
phase for restoring controlled state after dispatching events.
We assume that the deepest event target is the thing that needs its state
restored.
* Drop special cases for onChange in wrappers
We're now not using anything special about onChange handling in the
wrappers. Yay!
* Test Fiber internals differently in ReactElement
Instead of being able to access the owner's instance via getPublicInstance(), we use the Fiber's stateNode. (Fiber does not have methods, it's just a structure!)
* Fix isCompositeComponentWithType for fiber
In ReactTestUtils.isCompositeComponentWithType, we provide a way to walk through Fiber's internals in place of using _currentElement.type. We keep support for non-fiber though.
* Test fiber reconciler consistently
Use typeof instance.tag to test if we're using the fiber reconciler
* Remove unnecessary comment
Prior to this, React was using a nextDebugID variable that was locally
scoped to both `instantiateReactComponent` and `ReactShallowRenderer`.
This caused problems when the debugIDs would collide, the `itemMap` in
`ReactComponentTreeHook` would be overwritten and tests would fail
with the message "Expected onBeforeMountComponent() parent and
onSetChildren() to be consistent".
This change shares the debugID with both modules thus preventing any
collisions in the future.
This splits DefaultInjection into one with all the properties
and event configuration and a separate one for the things that
are relevant to he stack reconciler.
That way we can reuse the property and event system for Fiber
without pulling in all the other stuff.
* Initial pass at the easy case of updates (updates that start at the root).
* Don't expect an extra componentWillUnmount call
It was fixed in #6613.
* Remove duplicate expectations from the test
* Fix style issues
* Make naming consistent throughout the tests
* receiveComponent() does not accept safely argument
* Assert that lifecycle and refs fire for error message
* Add more tests for mounting
* Do not call componentWillMount twice on error boundary
* Document more of existing behavior in tests
* Do not call componentWillUnmount() when aborting mounting
Previously, we would call componentWillUnmount() safely on the tree whenever we abort mounting it. However this is likely risky because the tree was never mounted in the first place.
People shouldn't hold resources in componentWillMount() so it's safe to say that we can skip componentWillUnmount() if componentDidMount() was never called.
Here, we introduce a new flag. If we abort during mounting, we will not call componentWillUnmount(). However if we abort during an update, it is safe to call componentWillUnmount() because the previous tree has been mounted by now.
* Consistently display error messages in tests
* Add more logging to tests and remove redundant one
* Refactor tests
* Split complicated tests into smaller ones
* Assert clean unmounting
* Add assertions about update hooks
* Add more tests to document existing behavior and remove irrelevant details
* Verify we can recover from error state
* Fix lint
* Error in boundary’s componentWillMount should propagate up
This test is currently failing.
* Move calling componentWillMount() into mountComponent()
This removes the unnecessary non-recursive skipLifecycle check.
It fixes the previously failing test that verifies that if a boundary throws in its own componentWillMount(), the error will propagate.
* Remove extra whitespace
This is needed for flat builds. It also lets us get rid of a bunch
of special cases in the build scripts.
It also allow us to just copy the source files into React Native
instead of having to build first to resolve the special cases.
* Remove onBeforeMountComponent hook event
It is unnecessary.
We now pass the element as part of onInstantiateComponent, and it can't change before mounting.
* Remove onComponentHasMounted hook event
It is unused after #7410.
* Replace on(Begin|End)ReconcilerTimer hook events
We already have onBeforeUpdateComponent.
Let's just have on(Before?)(Mount|Update|Unmount)Component and stick with them.
This removes double event dispatches in some hot spots.
* Remove onComponentHasUpdated hook
The tests still pass so presumably it was not necessary.
* Add missing __DEV__ to TestUtils code
* Replace on(InstantiateComponent|SetParent) with onBeforeMountComponent
This lets us further consolidate hooks.
The parent ID is now passed as an argument to onBeforeMountComponent() with the element.
* Remove onMountRootComponent hook event
It is unnecessary now that we pass the parent ID to onBeforeMountComponent.
* Use parentDebugID = 0 both for roots and production
This removes some awkward branching.
* Remove unnecessary indirection from the tree hook
* Replace onSetDisplayName, onSetOwner, onSetText with one event
Less events is better.
onSetDisplayName, onSetOwner, and onSetText only existed because we didn't initially track elements.
* Remove unused variables
* PropTypes: distinguish nullable from optional object field
This gives a more precise message (no type semantics change) to the case of passing a field in an object, but whose value is `null`:
Before:
```js
propTypes: {
foo: React.PropTypes.number.isRequired
}
```
Would scream "Required prop `foo` was not specified in `MyComp`".
Now it'll be "Required prop `foo` was specified in `MyComp`, but its value is `null`.".
Works as expected in nested objects.
This fixes the issue of a component transitively passing a `null`, specifying the correct field to the child but have the child tell it that it didn't provide the prop.
Optional field and nullable are two different things anyway.
* Add missing test case.
* Reword messages.
Although it is unreasonable to set every possible property for
simulated events, `type` is useful for event handlers that are shared
between types and potentially have different behaviors.
Previously, this threw:
```
FAIL src/test/__tests__/ReactTestUtils-test.js (7.291s)
● ReactTestUtils › it can fail context when shallowly rendering
- TypeError: Cannot read property '_source' of null
at describeID (src/renderers/shared/devtools/ReactComponentTreeDevtool.js:70:46)
at Object.ReactComponentTreeDevtool.getStackAddendumByID (src/renderers/shared/devtools/ReactComponentTreeDevtool.js:203:15)
at checkReactTypeSpec (src/isomorphic/classic/types/checkReactTypeSpec.js:76:58)
at ReactCompositeComponentMixin._checkContextTypes (src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:668:5)
at ReactCompositeComponentMixin._processContext (src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:607:14)
at ReactCompositeComponentMixin.mountComponent (src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:191:30)
at ReactShallowRenderer._render (src/test/ReactTestUtils.js:483:14)
at _batchedRender (src/test/ReactTestUtils.js:460:12)
at ReactDefaultBatchingStrategyTransaction.Mixin.perform (src/shared/utils/Transaction.js:140:20)
at Object.ReactDefaultBatchingStrategy.batchedUpdates (src/renderers/shared/stack/reconciler/ReactDefaultBatchingStrategy.js:65:19)
at Object.batchedUpdates (src/renderers/shared/stack/reconciler/ReactUpdates.js:112:20)
at ReactShallowRenderer.render (src/test/ReactTestUtils.js:453:16)
at Spec.eval (src/test/__tests__/ReactTestUtils-test.js:289:34)
at jasmine.Block.execute (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:1067:17)
at jasmine.Queue.next_ (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2100:31)
at jasmine.Queue.start (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2053:8)
at Spec.jasmine.Spec.execute (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2380:14)
at jasmine.Queue.next_ (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2100:31)
at onComplete (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2096:18)
at Spec.jasmine.Spec.finish (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2354:5)
at eval [as onComplete] (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2381:10)
at jasmine.Queue.next_ (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2110:14)
at eval (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2090:18)
at Timeout.e [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:440:19)
at tryOnTimeout (timers.js:224:11)
at Timer.listOnTimeout (timers.js:198:5)
```
This adds some tests for getElement() and verifies that it works for text components too.
The code that calls the instrumentation is fixed where necessary so that the tests pass.
We extract common logic between DOM and native tests so they don't diverge.
Also, rather than build a tree object in advance for testing, we will walk the tree on the go.
This lets us have much more specific error messages with a clear path when something goes wrong.
For clarity.
I left "native event" as-is because there's a lot of it, it's not particularly ambiguous, and SimulateNative/nativeTouchData are public API in ReactTestUtils.
This makes it easier to figure out where the docs live.
Googling for e.g. `react-addons-update` also works, but this should
make things easier for people that hyperclick directly to the source.
ReactDOMInput and a few other classes handle change event by scheduling updateWrapper() in an asap().
It gets executed after the batch, which confuses ReactPerf that expects all DOM writes to happen during a batch.
Since this implementation of ReactPerf relying on the stack is going away, let's plug the hole temporarily by ignoring DOM writes that occur during postponed updateWrapper(). In any case, they have no relation to actual calculations of wasted renders, as they don't occur due to updateComponent(), but rather due to onChange() special DOM behavior.
This fixes#5548