Commit Graph

7320 Commits

Author SHA1 Message Date
Ben Alpert fa82e3e9d6 Update website on Travis when only new files are added (#8037)
This build didn't commit the new files because no existing files were changed:

https://travis-ci.org/facebook/react/jobs/169622664

This should work better.
2016-10-22 21:41:29 +01:00
Christopher Chedeau 4812f26915 Update components-and-props.md
fb indent style
2016-10-21 18:30:25 -07:00
Christopher Chedeau eb118b7037 Update react-without-jsx.md
Facebook codestyle
2016-10-21 14:30:35 -07:00
Dan Abramov d1a61ee7f4 Fix redirects 2016-10-21 22:02:30 +01:00
Dan Abramov 1f818f2740 Minor doc tweaks 2016-10-21 21:47:43 +01:00
Kevin Lacker 455d2d1b48 New Documentation 2016-10-21 20:59:08 +01:00
Sebastian Markbåge 8cac523bea Merge pull request #8029 from sebmarkbage/fiberreturnfromtoprender
Quick fix to the return top level problem
2016-10-21 14:59:01 -04:00
Sebastian Markbage 6e7c89ed8a Quick fix to the return top level problem
This doesn't deal with the fact that work is usually deferred
so this will return null for first render (except in sync tests).
It also doesn't deal with top levels being fragments etc.
It doesn't deal with the host instance type being a wrapper
around the public instance. This needs to be unified with refs
and findDOMNode better.

However, this does expose that we reactComponentExpect and
ReactTestUtils doesn't work very well with Fiber.
2016-10-21 11:58:40 -07:00
Sebastian Markbåge 9b1b40ca93 Merge pull request #8015 from sebmarkbage/fiberclassinit
[Fiber] Add more life-cycles
2016-10-21 14:57:51 -04:00
Sebastian Markbage 37ca3874af Add unit tests for aborted life-cycles
This tests the life-cycles when work gets aborted.
2016-10-21 11:57:24 -07:00
Sebastian Markbage c862ba719e Fallback to current props if memoizedProps is null
If work has progressed on a state update that gets resumed
because of another state up, then we won't have an new
pendingProps, and we also won't have any memoizedProps because
it got aborted before completing. In that case, we can just
fallback to the current props.

I think that they can't have diverged because the only way they
diverge is if there is new props.

This lets us bail out on state only updates in more cases which
the unit tests reflect.
2016-10-21 11:57:24 -07:00
Sebastian Markbage b72c27ce5d Don't schedule NoWork as the next work
We currently only filter out "NoWork" in the beginning of this
function. If the NoWork root is after the one with work it will
show up in the second loop. There's probably a more efficient
way of doing this but this works for now.

This showed up in this PR because a new unit test gets unblocked
which ends up with this case.
2016-10-21 11:57:24 -07:00
Sebastian Markbage a87ec42f2a Add more life-cycles to Fiber
This refactors the initialization process so that we can share
it with the "module pattern" initialization.

There are a few new interesting scenarios unlocked by this.
E.g. constructor -> componentWillMount -> shouldComponentUpdate
-> componentDidMount when a render is aborted and resumed.
If shouldComponentUpdate returns true then we create a new
instance instead of trying componentWillMount again or
componentWillReceiveProps without being mounted.

Another strange thing is that the "previous props and state"
during componentWillReceiveProps, shouldComponentUpdate and
componentWillUpdate are all the previous render attempt. However,
componentDidMount's previous is the props/state at the previous
commit. That is because the first three can execute multiple
times before a didMount.
2016-10-21 11:57:24 -07:00
Toru Kobayashi a6728f961c [Fiber] Add unit tests for ReactDOMFiber (#8016) 2016-10-21 00:44:23 -04:00
Sebastian Markbåge 4132cc4d3e Fix lint with yarn (#7997)
I couldn't figure out how to do this yarn alone so I ended up
just manually hacking the yarn to force a downgrade of babylon
to 6.8.0 since otherwise it gets resolved to 6.12.0 which is
broken.
2016-10-20 17:49:40 -04:00
Ben Alpert a8beab3341 Fix captured/bubbled in ReactNativeTreeTraversal (#8019)
Follow-up to #7741. Added a test for RN event bubbling that fails before the fix.
2016-10-20 11:17:06 -07:00
Sebastian Markbåge a5195102d4 [Fiber] Some setState related issues (#8010)
* Use the memoized props/state from the workInProgress

We don't want to use the "current" props/state because if we have
started work, then pause and continue then we'll have the newer
props/state on it already. If it is not a resume, it should be the
same as current.

* Deprioritize setState within a deprioritized tree

Currently we flag the path to a setState as a higher priority
than "offscreen". When we reconcile down this tree we bail out
if it is a hidden node. However, in the case that node is already
completed we don't hit that bail out path. We end up doing the
work immediately which ends up committing that part of the tree
at a higher priority.

This ensures that we don't let a deprioritized subtree get
reconciled at a higher priority.

* Bump idx in unit test

This proves that this number is actually deprioritized.
2016-10-19 13:32:37 -04:00
Toru Kobayashi 3d7869ab0e [Fiber] Add a unit test for ReactTopLevelText (#8001) 2016-10-18 14:39:49 -04:00
Dan Abramov 9bfa45bd2d Update Flow and fix issues (#8006) 2016-10-18 15:26:40 +01:00
Dan Abramov 75367673cf Fix Haste header (#8005) 2016-10-18 14:06:08 +01:00
Andrew Clark 663d4a539b Merge pull request #8000 from piperchester/patch-1
Fix grammatical error
2016-10-17 21:26:22 -07:00
Piper Chester 31f5edc492 Fix grammatical error 2016-10-17 21:13:33 -07:00
Sebastian Markbage fae3e5308b Use memoizedState in componentDidUpdate
We forgot to clone this value so it didn't work before.
This is covered by existing tests in ReactDOMProduction.
2016-10-17 16:21:06 -04:00
Sebastian Markbage 685d65bfb6 No duck typing on the root
The root is always a host container.
2016-10-17 16:21:06 -04:00
Sebastian Markbage bc5dfd5358 Break out some Class Component logic into separate module
Refactors the class logic a bit.

I moved scheduleUpdate out into the scheduler since that's where
the scheduling normally happens. I also moved it so that we can
rely on hoisting to resolve the cycle statically.

I moved the updater to a new class component file. I suspect we
will need a bit of space in here since the class initialization
code is quite complex.

The class component dependency is currently fixed in BeginWork
so we can't move complete or commit phase stuff to it. If we need
to, we have to initialize it in the scheduler and pass it to the
other phases.
2016-10-17 16:21:06 -04:00
Sebastian Markbage 9c25538e13 Fix resuming bug
If we abort work but have some completed, we can bail out if
the shouldComponentUpdate returns true. However, then we have
a tree that is low priority. When we bailout we currently use
the "current" tree in this case. I don't think this is right.
I'm not sure why I did that.

Similarly, when we complete we use the "current" props if we
didn't have pending props to do. However, we should be using
the memoized props of that tree if it is a pending work tree.

Added a unit test that covers these two cases.
2016-10-17 16:17:30 -04:00
Sebastian Markbage e59e5b280f Invoke all null ref calls before any new ref calls
This reorganizes the two commit passes so that all host
environment mutations happens before any life-cycles. That means
that the tree is guaranteed to be in a consistent state at that
point so that you can read layout etc.

This also lets us to detach all refs in the same pass so that
when they get invoked with new instances, that happens after it
has been reset.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 3717b71c64 Resolve ref callbacks
During the deletion phase we call detachRefs on any deleted refs.

During the insertion/update phase we call attachRef on class
and host components.

Unfortunately, when a ref switches, we are supposed to call all
the unmounts before doing any mounts. This means that we have to
expact the deletion phase to also include updates in case they
need to detach their ref.
2016-10-17 16:17:30 -04:00
Sebastian Markbage c44c7eaa1b Fire componentDidMount/componentDidUpdate life-cycles
These happen in the commit phase *before* the setState callback.

Unfortunately, we've lost the previous state at this point since
we've already mutated the instance. This needs to be fixed
somehow.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 90993c5324 Call componentWillUnmount during deletion phase
While we're deleting nodes, we need to call the unmount
life-cycle. However, there is a special case that we don't want
to keep deleting every host node along the way since deleting the
top node is enough.
2016-10-17 16:17:30 -04:00
Sebastian Markbage a98aba4d73 Always override priority level when visiting children
It is not possible for a child to have a higher priority level
than we're reconciling at, unless we intentionally want to
down-prioritize it.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 43645a6586 Reset effect list when we recompute children
We only use the effect list when we reuse our progressed children.
Otherwise it needs to reset to null.

In all other branches, other than bailoutOnLowPriority, we
revisit the children which recreates this list.

We should also not add fibers to their own effect list since it
becomes difficult to perform work on self without touching the
children too. Nothing else does that neither.

Since that means that the root isn't added to an effect list we
need to special case the root.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 1d437dc9ad Remove beginWork shortcut
This shortcut had a bug associated with it. If beginWork on this
child returns null, then we don't call completeWork on that fiber.

Since removing this short cut adds another time check, we have to
add a single unit of time in tests to account for the top level
call now taking one more unit.

This was also the only recursive call in all of fiber so it's nice
to get rid of it to guarantee that a flat stack is possible.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 5de2821372 Move child updates to use the reconciled effects
Instead of passing the full list of children every time to
update the host environment, we'll only do inserts/deletes.

We loop over all the placement effects first and then later
we do the rest.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 442ab71fc7 Append deletions to the effect list
First clear any progressed deletions for any case where we start
over with the "current" set of children.

Once we've performed a new reconciliation we need to add the
deletions to the side-effect list (which we know is empty because
we just emptied it).

For other effects, instead of just adding a fiber to an effect
list we need to mark it with an update. Then after completion
we add it to the the effect list if it had any effects at all.

This means that we lose the opportunity to control if a fiber
gets added before or after its children but that was already
flawed since we want certain side-effects to happen before others
on a global level.

Instead, we'll do multiple passes through the effect list.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 901691eb92 Tag the fiber with the kind of side-effect that was applied to it
This allow us to track what kind of side-effect this was even
though we only have a single linked list for all side-effects.
2016-10-17 16:17:30 -04:00
Sebastian Markbage e9e645a9b1 Deletion tracking
When we reconcile children we need to track the deletions that
happen so that we can perf side-effects later as a result. The
data structure is a linked list where the next pointer uses the
nextEffect pointer.

However, we need to store this side-effect list for reuse if we
end up reusing the progressedChild set. That's why I add a
separate first/last pointer into this list so that we can keep it
for later.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 0dc840a2b9 Fast path for create child
When we don't have any previous fibers we can short cut this path
knowing that we will never have any previous child to compare to.

This also ensures that we don't create an empty Map in this case.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 3979bb9e24 Don't track side-effects unless needed
We don't need to track side-effects for a parent that has never
been mounted before. It will simply inject all its children when
it completes.
2016-10-17 16:17:30 -04:00
Sebastian Markbage cccc4ae2c6 Add index field to each fiber
We use this to track the index slot that this Fiber had at
reconciliation time. We will use this for two purposes:

1) We use it to quickly determine if a move is needed.

2) We also use it to model a sparce linked list, since we can have
null/false/undefined in our child set and these take up a slot for
the implicit key.
2016-10-17 16:17:30 -04:00
Sebastian Markbage edaf08fcfe Fiber child reconciliation
This implements the first step to proper child reconciliation.
It doesn't yet track side-effects like insert/move/delete but has
the main reconciliation algorithm in place.

The goal of this algorithm is to branch early and avoid rechecking those conditions. That leads to some duplications of code.

There are three major branches:

- Reconciling a single child per type.
- Reconciling all children that are in the same slot as before from the beginning.
- Adding remaining children to a temporary Map and reconciling them by scanning the map.

Even when we use the Map strategy we have to scan the linked list to line up "same slot" positions because React, unlike Inferno, can have implicit keys interleaved with explicit keys.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 13f01be64f Enable text updates in ReactNoop
We'll enable updating of text nodes. To be able to test that we
need the text nodes to be mutable. They're currently just strings
in the Noop renderer so this makes them an object instead.

That exposed a bug in ReactFiberCommitWork for text nodes.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 362e56a1c1 Add comment about bug in yields
This needs to be fixed somehow. The reconciler could know if you
are mounting this continuation into the same spot as before and
then clone it. However, if the continuation moves, this info is
lost. We'd try to unmount it in one place and mount the same fiber
in another place.
2016-10-17 16:17:30 -04:00
Sebastian Markbage c3310d3e32 Fix MultiChild tests so they work with Fiber
Dropped the unnecessary use of findDOMNode.
Dropped unnecessary arrow functions.
Math.random() -> id counter, since this used to be
non-deterministic which is not ideal for unit tests.

getOriginalKeys() used to rely on implementation details
to scan that the internal data structure maintained its
structure, however, since that is unobservable we don't
need to test the internal data structure itself. We're
already testing refs and dom structure which is the only
observable effect of the reorder.
2016-10-17 16:17:30 -04:00
Sebastian Markbage 8d3a58de62 Silence Fiber warning when the feature flag is on
When the feature flag is on, we should silence the warning since
we're explicitly testing it. This is needed when running unit
tests with the flag on.
2016-10-17 16:17:30 -04:00
Sebastian Markbage cafa7b284a Add Text node types
These nodes rendering into Text nodes in the DOM.

There is a special case when a string is a direct child of a host
node. In that case, we won't reconcile it as a child fiber. In
terms of fibers, it is terminal. However, the host config special
cases it.

It is kind of unfortunate that we have to special case this kind
of child in the HostConfig. It would be nice to unify this with
other types of child instances. Text nodes have some weird special
cases, but those special cases tend to *vary* by environment.
They're not the same special cases so not sure how valuable it is
to have a special protocol and special types for it.
2016-10-17 16:17:30 -04:00
Sebastian Markbage e0a305350b Add Fragment fiber type
We currently treat nested arrays as a unique namespace from top
level children. So that these won't share key namespaces. This
adds a new fiber type that will represent the position of a
fragment.

This is only used for nested arrays. Even if you return an array
from a composite component, we don't need this since they share
namespace with a single top level component.

This still doesn't implement the complete reconciliation
algorthim in child fiber. That's coming later.
2016-10-17 16:17:30 -04:00
Dan Abramov 7b7eddcc72 Add @preventMunge directives to classes (#7994) 2016-10-17 21:07:17 +01:00
Dan Abramov c2d5833e98 Ignore root docs folder in Flow config
Otherwise Flow finds obscure files in docs/vendor.
Seems like you'd only get them if you have a local checkout of docs Ruby dependencies.
This explains why Travis didn't fail.
2016-10-17 16:12:07 +01:00
Dan Abramov f33f03e357 Support passthrough updates for error boundaries (#7949)
* 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
2016-10-15 18:13:56 +01:00