Commit Graph
19463 Commits
Author SHA1 Message Date
Sebastian Markbåge 9c6de716d0 Add withSuspenseConfig API (#15593)
* Add suspendIfNeeded API and a global scope to track it

Adds a "current" suspense config that gets applied to all updates scheduled
during the current scope.

I suspect we might want to add other types of configurations to the "batch"
so I called it the "batch config".

This works across renderers/roots but they won't actually necessarily go
into the same batch.

* Add the suspenseConfig to all updates created during this scope

* Compute expiration time based on the timeout of the suspense config

* Track if there was a processed suspenseConfig this render pass

We'll use this info to suspend a commit for longer when necessary.

* Mark suspended states that should be avoided as a separate flag

This lets us track which renders we want to suspend for a short time vs
a longer time if possible.

* Suspend until the full expiration time if something asked to suspend

* Reenable an old test that we can now repro again

* Suspend the commit even if it is complete if there is a minimum delay

This can be used to implement spinners that don't flicker if the data
and rendering is really fast.

* Default timeoutMs to low pri expiration if not provided

This is a required argument in the type signature but people may not
supply it and this is a user facing object.

* Rename to withSuspenseConfig and drop the default config

This allow opting out of suspending in some nested scope.

A lot of time when you use this function you'll use it with high level
helpers. Those helpers often want to accept some additional configuration
for suspense and if it should suspend at all. The easiest way is to just
have the api accept null or a suspense config and pass it through. However,
then you have to remember that calling suspendIfNeeded has a default.

It gets simpler by just saying tat you can pass the config. You can have
your own default in user space.

* Track the largest suspense config expiration separately

This ensures that if we've scheduled lower pri work that doesn't have a
suspenseConfig, we don't consider its expiration as the timeout.

* Add basic tests for functionality using each update mechanism

* Fix issue when newly created avoided boundary doesn't suspend with delay

* Add test for loading indicator with minLoadingDurationMs option
2019-05-16 16:51:18 -07:00
Dominic Gannaway 1160b37691 Event API: Add responder allowMultipleHostChildren flag (#15646) 2019-05-16 19:03:38 +01:00
Dominic Gannaway 95e06ac3d0 Event API: isTargetWithinEventResponderScope on unmounted event components (#15672) 2019-05-16 18:59:59 +01:00
Sunil Pai d278a3ff8b act() - s / flushPassiveEffects / Scheduler.unstable_flushWithoutYielding (#15591)
* s/flushPassiveEffects/unstable_flushWithoutYielding

a first crack at flushing the scheduler manually from inside act(). uses unstable_flushWithoutYielding(). The tests that changed, mostly replaced toFlushAndYield(...) with toHaveYielded(). For some tests that tested the state of the tree before flushing effects (but still after updates), I replaced act() with bacthedUpdates().

* ugh lint

* pass build, flushPassiveEffects returns nothing now

* pass test-fire

* flush all work (not just effects), add a compatibility mode

of note, unstable_flushWithoutYielding now returns a boolean much like flushPassiveEffects

* umd build for scheduler/unstable_mock, pass the fixture with it

* add a comment to Shcduler.umd.js for why we're exporting unstable_flushWithoutYielding

* run testsutilsact tests in both sync/concurrent modes

* augh lint

* use a feature flag for the missing mock scheduler warning

I also tried writing a test for it, but couldn't get the scheduler to unmock. included the failing test.

* Update ReactTestUtilsAct-test.js

- pass the mock scheduler warning test,
- rewrite some tests to use Scheduler.yieldValue
- structure concurrent/legacy suites neatly

* pass failing tests in batchedmode-test

* fix pretty/lint/import errors

* pass test-build

* nit: pull .create(null) out of the act() call
2019-05-16 17:12:36 +01:00
Dominic Gannaway aad5a264d2 Event API: ensure calculateResponderRegion accounts for page offset (#15671) 2019-05-16 17:09:41 +01:00
Dan Abramov bb89b4eacc Bail out of updates in offscreen trees (#15666)
* Bail out of updates in offscreen trees

* Address review
2019-05-16 11:12:05 +01:00
Andrew Cherniavskii 4bf88ddeca Fix <embed> not triggering onLoad (#15614) 2019-05-16 11:05:20 +02:00
Andrew Clark f961050a37 Always flushPassiveEffects before rendering
I  mistakenly wrapped this in the revertPassiveEffectsChange feature
flag. It should flush regardless of the flag.
2019-05-15 18:13:05 -07:00
Andrew Clark b899819e77 Use dynamic flag in test renderer in www (#15662)
Uses a dynamic flag in www's test renderer build so we can condtionally
disable the passive effects bugfix. Matches the dynamic flag used in
the www React DOM build.
2019-05-15 14:55:50 -07:00
Brian Vaughn f10a6b379c Improve scanning Profiler chart for deep renders 2019-05-15 14:20:36 -07:00
Andrew Clark d34b457ce2 Feature flag to revert #15650 (#15659)
PR #15650 is a bugfix but it's technically a semantic change that could
cause regressions. I don't think it will be an issue, since the
previous behavior was both broken and incoherent, but out of an
abundance of caution, let's wrap it in a flag so we can easily revert
it if necessary.
2019-05-15 13:38:06 -07:00
Andrew Clark 668fbd651b Fix serial passive effects (#15650)
* Failing test for false positive warning

* Flush passive effects before discrete events

Currently, we check for pending passive effects inside the `setState`
method before we add additional updates to the queue, in case those
pending effects also add things to the queue.

However, the `setState` method is too late, because the event that
caused the update might not have ever fired had the passive effects
flushed before we got there.

This is the same as the discrete/serial events problem. When a serial
update comes in, and there's already a pending serial update, we have to
do it before we call the user-provided event handlers. Because the event
handlers themselves might change as a result of the pending update.

This commit moves the `flushPassiveEffects` call to before the discrete
event handlers are called, and removes it from the `setState` method.
Non-discrete events will not cause passive effects to flush, which is
fine, since by definition they are not order dependent.
2019-05-14 18:08:10 -07:00
Dominic Gannaway b0657fde6a Event API: ensure getFocusableElementsInScope handles suspended trees (#15651) 2019-05-15 01:08:30 +01:00
Sebastian Markbåge 8af90c8972 Add test for nested avoided boundaries (#15636)
* Add test for nested avoided boundaries

* Add test for top level avoided boundaries
2019-05-14 14:41:45 -07:00
Brian Vaughn 6fd2e72b5e Minor nits 2019-05-14 11:01:41 -07:00
Dominic Gannaway af19e2eb2f Event API: adds pointerType to Focus events (#15645) 2019-05-14 15:59:36 +01:00
Ivan Babak 76e569992b Cleanup profile export/import data types, add export/import test
Strengthened the I/O-boundary type conversion logic.

Fixed type inconsistencies uncovered by removing `any` and
by making explicit type annotations and transformations.

In particular, these were likely malformed when restored from a file:
- `commitDetails`
- `interactions`
- `initialTreeBaseDurations`

The mismatches were Map vs interleaved Array.
2019-05-13 23:59:01 -07:00
Andrew Clark cc24d0ea56 Invariant that throws when committing wrong tree (#15517)
If React finishes rendering a tree, delays committing it (e.g.
Suspense), then subsequently starts over or renders a new tree, the
pending tree is no longer valid. That's because rendering a new work-in
progress mutates the old one in place.

The current structure of the work loop makes this hard to reason about
because, although `renderRoot` and `commitRoot` are separate functions,
they can't be interleaved. If they are interleaved by accident, it
either results in inconsistent render output or invariant violations
that are hard to debug.

This commit adds an invariant that throws if the new tree is the same as
the old one. This won't prevent all bugs of this class, but it should
catch the most common kind.

To implement the invariant, I store the finished tree on a field on the
root. We already had a field for this, but it was only being used for
the unstable `createBatch` feature.

A more rigorous way to address this type of problem could be to unify
`renderRoot` and `commitRoot` into a single function, so that it's
harder to accidentally interleave the two phases. I plan to do something
like this in a follow-up.
2019-05-13 16:15:50 -07:00
Andrew Clark 83fc258f29 Remove <ConcurrentMode /> (#15532)
Use createSyncRoot instead.
2019-05-13 16:10:00 -07:00
Andrew Clark 283ce53204 Add ReactDOM.unstable_createSyncRoot (#15504)
* Add ReactDOM.unstable_createSyncRoot

- `ReactDOM.unstable_createRoot` creates a Concurrent Mode root.
- `ReactDOM.unstable_createSyncRoot` creates a Batched Mode root. It
does not support `createBatch`.
- `ReactDOM.render` creates a Legacy Mode root. It will eventually be
deprecated and possibly moved to a separate entry point, like
`react-dom/legacy`.

* Rename internal ReactRoot types
2019-05-13 15:30:03 -07:00
Brian Vaughn 1723c5d316 Changed "Unknown" fallback displayName to "Anonymous". Added memo/forwardRef labels to Profiler charts. 2019-05-13 15:26:14 -07:00
Brian Vaughn 6b4c758338 CSS tweaks 2019-05-13 14:51:56 -07:00
Andrew Clark 862f499fac Add Batched Mode (#15502)
* Add Batched Mode

React has an unfortunate quirk where updates are sometimes synchronous
-- where React starts rendering immediately within the call stack of
`setState` — and sometimes batched, where updates are flushed at the
end of the current event. Any update that originates within the call
stack of the React event system is batched. This encompasses most
updates, since most updates originate from an event handler like
`onClick` or `onChange`. It also includes updates triggered by lifecycle
methods or effects. But there are also updates that originate outside
React's event system, like timer events, network events, and microtasks
(promise resolution handlers). These are not batched, which results in
both worse performance (multiple render passes instead of single one)
and confusing semantics.

Ideally all updates would be batched by default. Unfortunately, it's
easy for components to accidentally rely on this behavior, so changing
it could break existing apps in subtle ways.

One way to move to a batched-by-default model is to opt into Concurrent
Mode (still experimental). But Concurrent Mode introduces additional
semantic changes that apps may not be ready to adopt.

This commit introduces an additional mode called Batched Mode. Batched
Mode enables a batched-by-default model that defers all updates to the
next React event. Once it begins rendering, React will not yield to
the browser until the entire render is finished.

Batched Mode is superset of Strict Mode. It fires all the same warnings.
It also drops the forked Suspense behavior used by Legacy Mode, in favor
of the proper semantics used by Concurrent Mode.

I have not added any public APIs that expose the new mode yet. I'll do
that in subsequent commits.

* Suspense in Batched Mode

Should have same semantics as Concurrent Mode.

* Use RootTag field to configure type of root

There are three types of roots: Legacy, Batched, and Concurrent.

* flushSync should not flush batched work

Treat Sync and Batched expiration times separately. Only Sync updates
are pushed to our internal queue of synchronous callbacks.

Renamed `flushImmediateQueue` to `flushSyncCallbackQueue` for clarity.
2019-05-13 14:30:39 -07:00
Brian Vaughn e2746ffd0e Merge branch 'enhancement/display-change' of https://github.com/submetu/react-devtools-experimental into submetu-enhancement/display-change 2019-05-13 14:12:27 -07:00
Brian Vaughn 982eb84a13 Merge pull request #271 from tux-tn/master
Replaced adm-zip with node-archiver
2019-05-13 14:10:21 -07:00
Brian Vaughn d9a0c42652 Bumped Profiler export version (since self durations are now included) 2019-05-13 14:04:53 -07:00
Brian Vaughn cf99c3ee6c Moved calculation of self duration to the backend/renderer
This enables self duration to be computed accurately despite component filters
2019-05-13 10:13:29 -07:00
Subhan 74706b0c86 updates snapshots 2019-05-13 19:00:11 +02:00
Subhan ec89ae88b6 Changes display of ForwardRef and Memo components 2019-05-13 18:58:03 +02:00
Dominic Gannaway fec74f99da Event API: ensure preventDefault works for nested targets (#15633) 2019-05-13 13:45:48 +01:00
Sarhan Aissi ad94f9ef08 Replaced adm-zip with node-archiver 2019-05-13 03:55:05 +01:00
Brian Vaughn ffef7ffc57 Merge pull request #268 from frankcalise/master
Fixed build chrome not working on Windows due to rm command not existing
2019-05-12 07:43:19 -07:00
Brian Vaughn faea8ed6a9 Delete package-lock.json 2019-05-12 07:43:07 -07:00
Frank Calise 285568825b Fixed build chrome not working on Windows due to rm command not existing 2019-05-12 10:12:17 -04:00
Andrew Clark edfedf3ae9 Fork ReactSharedInternals for UMD builds (#15617) 2019-05-10 13:51:39 -07:00
Andrew Clark 39ef609e7c Update test to fix CI 2019-05-10 11:12:24 -07:00
Andrew Clark 5b6eb55e1c Remove scheduler from React package dependencies (#15616)
Scheduler is used by the renderers, but not the isomorphic package.
2019-05-10 11:01:04 -07:00
Sebastian Markbåge 0803d22479 Don't consider "Never" expiration as part of most recent event time (#15606)
* Don't consider "Never" expiration as part of most recent event time

This doesn't happen with deprioritization since those are not "updates"
by themselves so they don't go into this accounting.

However, they are real updates if they were scheduled as Idle pri using
the scheduler explicitly. It's unclear what suspense should do for these
updates. For offscreen work, we probably want them to commit immediately.
No point in delay them since they're offscreen anyway. However if this is
an explicit but very low priority update that might not make sense.
So maybe this means that these should have different expiration times?

In this PR I just set the suspense to the lowest JND.

However, we don't want is for these things to commit earlier in case
they got batched in with other work so I also ensured that they're not
accounted for in in the workInProgressRootMostRecentEventTime calculation
at all. This makes them commit immediately if they're by themselves, or
after the JND of whatever they were batched in with.

Ultimately, I think that we should probably never schedule anything at
Never that isn't truly offscreen so this should never happen.

However, that begs the question what happens with very low pri work that
suspends. Do we always work at that level first?

* Adjust test to account for the new shorter suspense time
2019-05-10 10:53:20 -07:00
Brian Vaughn b74f3f507a Added basic tests for InspectedElementContext 2019-05-10 09:13:54 -07:00
Brian Vaughn 61ab40c15c Test utils actSuspense -> actAsync 2019-05-10 08:27:14 -07:00
Brian Vaughn 8536995b11 Merge pull request #264 from bvaughn/filter-owners-list
Fetch owners list from renderer (using suspense)
2019-05-10 08:10:24 -07:00
Brian Vaughn ac0022bf4a Added more tree context tests 2019-05-10 08:07:27 -07:00
Dominic Gannaway 90f54d77f3 Event API: add follow up event unwind test (#15612) 2019-05-10 13:36:54 +01:00
Dominic Gannaway 91a044e31f Event API: add key modifiers to Press events (#15611) 2019-05-10 13:32:11 +01:00
Sunil Pai 7aaef6f41f reverting the rename 2019-05-10 12:18:40 +01:00
Sunil Pai 6243d19b9c pretty, witty, fine 2019-05-10 12:16:43 +01:00
Sunil Pai ae3b98f5ad rewrite test act helpers based on react/#15591
This simplifies your test helpers to loop until all timers are flushed (including the ones that get queued after updates), and works in concurrent mode. I also renamed actSuspense to actAsync to be clearer.
2019-05-10 12:13:14 +01:00
Brian Vaughn 7160f6f584 Fixed owners stack direction and added current element to stack 2019-05-09 18:11:17 -07:00
Brian Vaughn 427f0f63c1 Added TreeContext tests 2019-05-09 15:52:50 -07:00
Brian Vaughn 5daf9b626f Fixed test describe name 2019-05-09 14:31:48 -07:00