Commit Graph

7762 Commits

Author SHA1 Message Date
Andrew Clark bb844a03b2 Use lastProgressedUpdate pointer instead of firstPendingUpdate
We need to be able to access both, and since the list uses forward
pointers, it makes more sense to point to the one that comes first.
Otherwise to get the last progressed update you have to start at the
beginning of the list.
2016-12-15 09:12:12 -08:00
Andrew Clark 94011e98a6 Separate priority for updates
When resetting the priority in the complete phase, check the priority of
the update queue so that updates aren't dropped.

Updates inside render, child cWRP, etc are no longer dropped.

The next step is sort the queue by priority and only flush updates that
match the current priority level.
2016-12-15 09:12:12 -08:00
Andrew Clark cb1ef03df9 Replace .hasForceUpdate with ForceUpdate effect
Removes another field from the update queue
2016-12-15 09:12:12 -08:00
Andrew Clark 6301086c35 Schedule callback effects while merging updates
This allows us to remove the hasCallback flag.
2016-12-15 09:12:12 -08:00
Andrew Clark cbba5ef9cc Don't drop updates until they are committed
Restructures the update queue to maintain a pointer to the first
pending update, which solves a few problems:

- Updates that occur during the begin phase (e.g. in cWRP of a child)
aren't dropped, like they are currently. This isn't working yet because
the work priority is reset during completion. The following item will
fix it.
- Sets us up to be able to add separate priorities to each update in
the queue. I'll add this in a subsequent commit.
2016-12-15 09:12:12 -08:00
Dan Abramov e36b38c1ca [Fiber] Fix some of the warnings (#8570)
* Implement component stack for some warnings in Fiber

* Keep Fiber debug source up to date

When an element changes, we should copy the source and owner again.
Otherwise they can get stale since we're not reading them from the element.

* Remove outdated TODOs from tests

* Explicitly specify Fiber types to include in the stack

Fixes an accidental omission when both source and owner are null but displayName exists.

* Fix mised Stack+Fiber test to not expect extra warnings

When we're in Fiber mode we don't actually expect that warning being printed.

* Warn on passing different props to super()

* Implement duplicate key warnings

We keep known keys in a set in development. There is an annoying special case where we know we'll check it again because we break out of the loop early.

One test in the tree hook regresses to the failing state because it checks that the tree hook works without a Set available, but we started using Set in this code. It is not essential and we can clean this up later when we decide how to deal with polyfills.

* Move ReactTypeOfWork to src/shared

It needs to be available both to Fiber and Isomorphic because the tree hook lives in Isomorphic but pretty-prints Fiber stack.

* Add dev-only ReactDebugCurrentFiber for warnings

The goal is to use ReactCurrentOwner less and rely on ReactDebugCurrentFiber for warning owner name and stack.

* Make Stack invariant messages more consistent

Fiber used a helper so two tests had the same phrasing.
Stack also used a helper for most invariants but hardcoded a different phrase in one place.
I changed that invariant message to use a helper which made it consistent with what it prints in Fiber.

* Make CSSPropertyOperations use getCurrentFiberOwnerName()

This gets mount-time CSS warnings to be printed.

However update-time warnings are currently ignored because current fiber is not yet available during the commit phase.

We also regress on HostOperation hook tests but this doesn't matter because it's only used by ReactPerf and it doesn't work with Fiber yet anyway. We'll have to think more about it later.

* Set ReactDebugCurrentFiber during the commit phase

This makes it available during updates, fixing the last failing test in CSSPropertyOperations.

* Add DOM warnings by calling hooks directly

It is not clear if the old hook system is worth it in its generic incarnation. For now I am just hooking it up to the DOMFiber renderer directly.

* Add client-side counterparts for some warning tests

This helps us track which warnings are really failing in Fiber, and which ones depend on SSR.
2016-12-15 08:36:58 -08:00
Brian Vaughn ab72f626de Merge pull request #8560 from bvaughn/react-native-fiber
ReactNative fiber renderer
2016-12-14 20:05:17 -08:00
Brian Vaughn 5266ca9312 Added new fiber-based renderer for native dubbed ReactNativeFiber 2016-12-14 18:39:22 -08:00
Ben Alpert ac241972bd mockImpl -> mockImplementation
D4329549
2016-12-14 14:21:51 -08:00
Ben Alpert ba8f24ba99 Prepare new composite child before removing old (#8572)
This matches what we do in Fiber -- and doing it this way is the only way we can prepare new views in the background before unmounting old ones.

In particular, this breaks this pattern:

```js
class Child1 extends React.Component {
  render() { ... }
  componentWillMount() {
    this.props.registerChild(this);
  }
  componentWillUnmount() {
    this.props.unregisterChild();
  }
}

class Child2 extends React.Component {
  render() { ... }
  componentWillMount() {
    this.props.registerChild(this);
  }
  componentWillUnmount() {
    this.props.unregisterChild();
  }
}

class Parent extends React.Component {
  render() {
    return (
      showChild1 ?
        <Child1
          registerChild={(child) => this.registered = child}
          unregisterChild={() => this.registered = null}
        /> :
        <Child2
          registerChild={(child) => this.registered = child}
          unregisterChild={() => this.registered = null}
        />
    );
  }
}
```

Previously, `this.registered` would always be set -- now, after a rerender, `this.registered` gets stuck at null because the old child's componentWillUnmount runs *after* the new child's componentWillMount.

A correct fix here is to use componentDidMount rather than componentWillMount. (In general, componentWillMount should not have side effects.) If Parent stored a list or set of registered children instead, there would also be no issue.
2016-12-14 11:14:50 -08:00
Gaëtan Renaudeau 931cad5aae Fix test renderer unmount (#8512)
* [react-test-renderer] unmount the inner instances

Fixes https://github.com/facebook/react/issues/8459

* add a test for https://github.com/facebook/react/issues/8459

* add new test in tests-passing.txt
2016-12-14 10:57:21 -05:00
Brian Vaughn 3def431543 Merge pull request #8568 from bvaughn/top-level-context-push-pop
HostRoot no longer pops context provider during complete phase
2016-12-13 17:27:47 -08:00
Brian Vaughn b4745ca72b HostRoot no longer pops context provider in complete phase
Also added an invariant warning to guard against context being popped too many times.
2016-12-13 17:26:19 -08:00
Andrew Clark 480e404fc8 Merge pull request #8528 from acdlite/callbacksemantics
Give setState callbacks componentWillUpdate semantics
2016-12-13 17:22:41 -08:00
Andrew Clark 97b7d0eff5 Test top-level callback when re-rendering with same element 2016-12-13 16:28:06 -08:00
Andrew Clark a930f09dfe Give setState callbacks componentWillUpdate semantics
This matches the behavior in Fiber. Normally we would change Fiber
to match Stack to minimize breaking changes for the initial release.
However, in this case it would require too large a compromise to change
Fiber to act like Stack.
2016-12-13 15:50:33 -08:00
Sebastian Markbåge bd425837a4 Merge pull request #8563 from sebmarkbage/enforcelowercasetags
Drop runtime validation and lower case coercion of tag names
2016-12-13 14:54:21 -08:00
Sebastian Markbage 6c1592f384 Pass type to the relevant host config methods
Instead of reading it from the DOM node.
2016-12-13 14:53:36 -08:00
Sebastian Markbage db489a4ade Only do runtime validation of tag names when createElement is not used
We introduced runtime validation of tag names because we used to generate
HTML that was supposed to be inserted into a HTML string which could've
been an XSS attack.

However, these days we use document.createElement in most cases. That
already does its internal validation in the browser which throws. We're now
double validating it. Stack still has a path where innerHTML is used and
we still need it there. However in Fiber we can remove it completely.
2016-12-13 14:53:36 -08:00
Sebastian Markbage 3092f63c6b Warn if upper-case tags are used
In #2756 we ended up using toLowerCase to allow case insensitive HTML tags.
However, this requires extra processing every time we access the tag or
at least we need to process it for mount and store it in an extra field
which wastes memory.

So instead, we can just enforce case sensitivity for HTML since this might
matter for the XML namespaces like SVG anyway.
2016-12-13 14:53:29 -08:00
Ben Alpert ec8b94e847 Disable coverage on PRs on Circle (#8569) 2016-12-13 14:27:25 -08:00
Brian Vaughn 369769aed4 Merge pull request #8558 from bvaughn/rename-initialize-core
Renamed InitializeJavaScriptAppEngine to InitializeCore
2016-12-12 21:32:53 -08:00
Dan Abramov 0f34bdc622 [Fiber] Remove array indirection in host context (#8544)
* Remove array indirection in host context

* Keep a single context stack with a null sentinel

This lets us keep subtrees separated without maintaining independent context arrays for subtrees.

* There is always exactly one null by the time we pop a portal

I was trying to be smart but didn't need to.

* Cache current context
2016-12-12 15:20:40 -08:00
Dan Abramov ef532fd4a4 [Fiber] Fix portal bugs (#8532)
* Enable additional (failing) portal tests

* Fix portal unmounting

When unmount a portal, we need to unmount *its* children from itself.
This is similar to what we would do for a root if we allowed deleting roots.

* Skip portals when looking for host siblings

A portal is not part of that host tree despite being a child.

* Fix comment typo

* Add a failing test for portal child reconciliation

It is failing because portal bails out of update, seeing null in pendingProps.
It is null because we set pendingProps to nextPortal.children, which is null in this test.

* Fix the bug when switching to a null portal child

If pendingProps is null, we do a bailout in beginWork.
This prevents unmounting of the existing child when the new child is null.

We fix this by changing portal fiber's pendingProps to be the portal object itself instead of its children.
This way, it is never null, and thus doesn't cause a false positive in the bailout condition.

* Add a comment about HostPortal in getHostSibling

* Revert the fix because I don't know why it worked

unmountHostComponents() should have worked despite finding the wrong parent because it should have changed the parent when pushing and popping the portals.

* Don't call commitDeletion recursively

This leads to a "Cannot find host parent" bug because commitDeletion() clears the return field.
When we're inside the loop, we assign node.sibling.return to node.return but by this moment node.return has already been nulled.
As a solution we inline code from commitDeletion() without the nulling.

It still fails tests but for a different reason (unrelated bug).

* Skip portal children in commitNestedUnmounts()

We are currently already visiting them in commitUnmount() portal case since it's recursive.
This condition avoids visting them twice.

* Set node.child.return before going deeper

It doesn't seem to influence existing tests but we have this protection in all other similar places.
It protects against infinite loops.

* Revert "Fix the bug when switching to a null portal child"

This reverts commit ed9747deed.

I'll solve this by using an array in place of null instead.

* Use [] for empty Portal pendingProps

This avoids a false positive bailout with pendingProps == null when portal is empty.
2016-12-12 14:18:55 -08:00
Brian Vaughn cdb38c1478 Renamed InitializeJavaScriptAppEngine mock to InitializeCore. 2016-12-12 13:55:58 -08:00
Brian Vaughn 7b7c0e4af5 Renamed InitializeJavaScriptAppEngine to InitializeCore 2016-12-12 11:23:25 -08:00
Brian Vaughn 0a3256ac15 Merge pull request #8557 from bvaughn/add-create-text-instance-param
Add rootContainerInstance param to createTextInstance
2016-12-12 11:20:46 -08:00
Brian Vaughn f8cb22ad83 Add rootContainerInstance param to createTextInstance.
This mirrors a recent change in params passed to  and cleans up a HACK currently required for the native fiber renderer to create text views.
2016-12-12 10:12:43 -08:00
comerc 92665e2cb1 Fix casing typo in jsx-in-depth.md (#8542) 2016-12-11 07:43:40 -06:00
Chris 39695dcd36 update example to use this.state (#8425)
- In the previous example, the code works even without using bind(this) in the constructor.
- the reason being handleClick doesn't even use `this` and its just calling the global function alert.
- this change make use of this via access this.state.
2016-12-11 07:41:48 -06:00
Sebastian Markbåge 14f05bfa89 ReactDOMFiber-test Rename portal -> usePortal (#8535)
Fixes lint since I used portal as a variable name.
We typically use a verb for functions.
2016-12-08 14:22:53 -08:00
Sebastian Markbåge 6c785ed524 Add unit tests for event bubbling in portals (#8509)
These bubble through the portal and up to the parent that rendered
the portal.
2016-12-08 13:51:21 -08:00
Sebastian Markbåge 3937bca8a2 Merge pull request #8491 from sebmarkbage/fibercurrenteventhandlers
[Fiber] Read Event Handlers from the "Current" Fiber
2016-12-08 13:49:51 -08:00
Dan Abramov c87ffc0beb [Fiber] Support SVG (#8490)
* Test that SVG elements get created with the right namespace

* Pass root to the renderer methods

* Keep track of host instances and containers

* Keep instances instead of fibers on the stack

* Create text instances in begin phase

* Create instance before bailing on offscreen children

Otherwise, the parent gets skipped next time.
We could probably create it later but this seems simpler.

* Tweak magic numbers in incremental tests

I don't understand why they changed but probably related to us moving some work into begin phase?

* Only push newly created nodes on the parent stack

Previously I was pushing nodes on the parent stack regardless of whether they were already in current or not.
As a result, insertions during updates were duplicated, and nodes were added to existing parents before commit phase.
Luckily we have a test that caught that.

* Fix lint

* Fix Flow

I had to wrap HostContext API into a closure so that it's parameterizeable with I and C.

* Use the same destructuring style in scheduler as everywhere else

* Remove branches that don't seem to run anymore

I'm not 100% sure this is right but I can't get tests to fail.

* Be explicit about the difference between type and tag

I was confused by th HACK comment so I learned how DOM and SVG work with casing and tried to write a more descriptive comment.
It also seems like passing fiber.type into finalizeInitialChildren() is a potential problem because DOM code assumes tag is lowercase.
So I added a similar "hack" to finalizeInitialChildren() that is identical to the one we have prepareUpdate() so if we fix them later, we fix both.

* Save and restore host context when pushing and popping portals

* Revert parent context and adding children in the begin phase

We can address this later separately as it is a more hot path.
This doesn't affect correctness of SVG container behavior.

* Add a test for SVG updates

This tests the "jump" reuse code path in particular.

* Record tests

* Read ownerDocument from the root container instance

This way createInstance() depends on the innermost container only for reading the namespace.

* Track namespaces instead of creating instances early

While we might want to create instance in the begin phase, we shouldn't let DOM guide reconciler design.
Instead, we are adding a new concept of "host context". In case of ReactDOMFiber, it's just the current namespace.
We are keeping a stack of host context values, ignoring those that are referentially equal.
The renderer receives the parent context and type, and can return a new context.

* Pop child context before reading own context and clarify API

It wasn't quite clear from the API which context was being returned by the renderer. Changed the API to specifically ask for child context, and thus to pop it before getting the current context.

This fixes the case with <foreignObject> to which I intended to give SVG namespace.

* Give SVG namespace to <svg> itself

* Don't allocate unnecessarily when reconciling portals

We create stacks lazily so that if portal doesn't contain <svg>s, we don't need to allocate.
We also reuse the same object for portal host context state instead of creating a new one every time.

* Add more tests for edge cases

* Fix up math namespace

* Maintain a separate container stack

* Fix rebase mistakes

* Unwind context on errors

* Reset the container state when reusing the object

* Add getChildHostContext() to ReactART

* Record tests
2016-12-08 13:10:47 -08:00
Charlie Garcia d77c42a26d Update CHANGELOG.md (#8518)
* Update CHANGELOG.md

* Update CHANGELOG.md
2016-12-08 12:07:53 -06:00
Ben Alpert 2161a6c92f Fix indentation for lint 2016-12-07 23:16:47 -08:00
Andrew Clark f56eb89389 Add additional scheduling tests
Tests whether certain types of work can be performed after the deadline
has expired.
2016-12-07 23:09:08 -08:00
Andrew Clark 3a7844cabb Consolidate workLoop and deferredWork loop
Solves a few things:

- Moves code out of performWork into workLoop so that it can
be optimized.
- errorLoop (now clearErrors) is no longer called recursively.
- Removes a while (true) loop inside performWork (not that it really
matters for optimization, since performWork contains a try block and
will be deopted, anyway).
2016-12-07 23:09:08 -08:00
Andrew Clark 24a83a5eeb Extract commit phase passes into separate functions
By splitting these out, we ensure that they can be optimized by the
JS engine.
2016-12-07 23:09:08 -08:00
Andrew Clark dcc17a966e Don't check for a pendingCommit on every iteration
Only check if we're in a deferred work batch and performUnitOfWork
returns null.
2016-12-07 23:09:08 -08:00
Andrew Clark 2508888a2b Errors thrown when detaching a ref should not interrupt unmount
If a ref throws while detaching, it should not prevent
componentWillUnmount from being called.

Additionally, errors thrown by removeChild should not be ignored, even
as the result of unmounting a failed subtree.
2016-12-07 23:09:08 -08:00
Andrew Clark 7e82214717 Error boundaries can only capture errors once per batch
Subsequent failures should propagate the error to the next boundary.
The conceptual model for this is

try {
  render();
} catch (error) {
  setStateToRecover();
  render();
}

Closes #8485
2016-12-07 23:09:08 -08:00
Andrew Clark 701d128fd1 Error recovery should have task priority
This uncovered a separate issue where some errors were being unscheduled
and rescheduled multiple times before flushing. Turns out we need to
check both a fiber and its alternate when determining if it represents a
failed unit of work. I didn't notice this before because we were
scheduling a new update on *every* boundary at the end of the commit
phase, not just the ones that captured an error during that commit. I
updated the unit tests to catch this in the future.
2016-12-07 23:09:08 -08:00
Andrew Clark d4dd3408bd Remove tryComponentDidMount/Update in favor of commit phase try block
We still need tryComponentWillUnmount because deletion should be non-
interruptible.

Refactoring the commit phase to better handle errors also allows us
to switch between fast and slow versions of the work loop. The slower
version runs whenever there are captured errors; it must check each
unit of work to see if it has failed. The faster version runs in the
normal case where there are no errors. Whenever an error is thrown, we
switch from the fast work loop to the slow work loop.
2016-12-07 23:09:08 -08:00
Andrew Clark db8539a47d Consolidate work loops
This makes it easier to track when we enter and exit a batch of work.

Further steps needed in this refactor:
- Get rid of tryComponentDidMount, tryComponentDidUpdate, etc. in
favor of the try-catch blocks that wrap each pass of the commit phase.
- Need to be able to switch between performing work that is possibly
failed (slower because it requires an extra check on each iteration) and
work that we know for sure has no errors.
2016-12-07 23:09:08 -08:00
Andrew Clark 5fcdebf712 Move commit phase outside of performUnitOfWork
This gives us the ability to complete a tree without having to commit it
within the same frame.
2016-12-07 23:09:08 -08:00
Brian Vaughn 9510ecfc5e Merge pull request #8521 from bvaughn/react-art-fiber
New fiber-based ReactART renderer
2016-12-07 18:35:48 -08:00
Ben Alpert fccebad780 Don't set innerHTML if content is empty (#8526)
From D4296244:

> Each [...] had a component with innerHTML = '', causing us to go into HTML parsing code in the browser. Doing this takes 0.03ms per parse call which was 10x slower than skipping it.
2016-12-07 17:20:57 -08:00
Ben Alpert 4d71a9c580 Probably fix facts tracker 2016-12-07 16:04:47 -08:00
Brian Vaughn 81cb216288 Imported new ReactART fiber renderer
Split ReactART into stack and fiber targets. Added new ReactART test case for recently-fixed bug.
2016-12-07 15:35:53 -08:00