Commit Graph

216 Commits

Author SHA1 Message Date
Sunil Pai
381d292d8d Merge branch 'master' into renderer-specific-act-warning 2019-05-17 15:07:09 +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
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
Andrew Clark
72ca3c60e7
Bump scheduler version to 0.14.0 (#15395) 2019-04-29 18:10:11 -07:00
Sunil Pai
29e2cc79a2 rename ReactShouldWarnActingUpdates to ReactActingRendererSigi, merge act/dom fixture folders 2019-04-18 16:44:21 +01:00
Sunil Pai
0aebde1ac0 lose ReactActingUpdatesSigil.js, use flushPassiveEffects as the acting sigil 2019-04-15 14:47:07 +01:00
Sunil Pai
e4d93a7de9 warn when using the wrong act() around create/updates
via #15319
This solves 2 specific problems -
- using the 'wrong' act() doesn't silence the warning
- using the wrong act logs a warning

It does this by using an empty object on the reconciler as the identity of ReactShouldWarnActingUpdates.current. We also add this check when calling createContainer() to catch the common failure of this happening right in the beginning.

make a proper fixture for act()

made fixtures/act for act(). specifically, this lets us tests how act behaves when you use the wrong act() for the wrong renderer. also mvoes dom/../act-dom.html to this fixture.

cleanup fixtures/dom/.gitignore

verify that it 'works' with art+dom

verify that it 'works' with art+test

augh prettier

tweak warning messages
2019-04-15 14:08:53 +01:00
Dominic Gannaway
aece8119cf
Refactor EventComponent logic + add onOwnershipChange callback (#15354) 2019-04-09 12:47:32 +01:00
Dominic Gannaway
4064ea9fa6
Experimental event API: Support EventComponent onUnmount responder callback (#15335) 2019-04-06 08:16:57 +01:00
Dominic Gannaway
4fbbae8afa
Add full TouchHitTarget hit slop (experimental event API) to ReactDOM (#15308) 2019-04-06 07:51:21 +01:00
Andrew Clark
4d5cb64aa2
Rewrite ReactFiberScheduler for better integration with Scheduler package (#15151)
* Rewrite ReactFiberScheduler

Adds a new implementation of ReactFiberScheduler behind a feature flag.
We will maintain both implementations in parallel until the new one
is proven stable enough to replace the old one.

The main difference between the implementations is that the new one is
integrated with the Scheduler package's priority levels.

* Conditionally add fields to FiberRoot

Some fields only used by the old scheduler, and some by the new.

* Add separate build that enables new scheduler

* Re-enable skipped test

If synchronous updates are scheduled by a passive effect, that work
should be flushed synchronously, even if flushPassiveEffects is
called inside batchedUpdates.

* Passive effects have same priority as render

* Revert ability to cancel the current callback

React doesn't need this anyway because it never schedules callbacks if
it's already rendering.

* Revert change to FiberDebugPerf

Turns out this isn't neccessary.

* Fix ReactFiberScheduler dead code elimination

Should initialize to nothing, then assign the exports conditionally,
instead of initializing to the old exports and then reassigning to the
new ones.

* Don't yield before commit during sync error retry

* Call Scheduler.flushAll unconditionally in tests

Instead of wrapping in enableNewScheduler flag.
2019-04-02 15:49:07 -07:00
Sunil Pai
aed0e1c30c
await act(async () => ...) (#14853)
This took a while, but I'm happy I went through it. Some key moments - recursively flushing effects, flushing microtasks on each async turn, and my team's uncompromising philosophy on code reuse. Really happy with this. I still want to expand test coverage, and I have some more small related todos, but this is good to land. On to the next one. 

Soundtrack to landing this - https://open.spotify.com/track/0MF8I8OUo8kytiOo8aSHYq?si=gSWqUheKQbiQDXzptCXHTg

* hacked up act(async () => {...})

* move stuff around

* merge changes

* abstract .act warnings and stuff. all renderers. pass all tests.

* move testutils.act back into testutils

* move into scheduler, rename some bits

* smaller bundle

* a comment for why we don't do typeof === 'function'

* fix test

* pass tests - fire, prod

* lose actContainerElement

* tighter

* write a test for TestRenderer

it's an odd one, because not only does sync act not flush effects correctly, but the async one does (wut). verified it's fine with the dom version.

* lint

* rewrote to move flushing logic closer to the renderer

the scheduler's `flushPassiveEffects` didn't work as expected for the test renderer, so I decided to go back to the hack (rendering a dumb container) This also makes reactdom not as heavy (by a few bytes, but still).

* move it around so the delta isn't too bad

* cleanups

fix promise chaining
propagate errors correctly
test for thenable the 'right' way
more tests!
tidier!
ponies!

* Stray comment

* recursively flush effects

* fixed tests

* lint, move noop.act into react-reconciler

* microtasks when checking if called, s/called/calledLog, cleanup

* pass fb lint

we could have globally changed our eslint config to assume Promise is available, but that means we expect a promise polyfill on the page, and we don't yet. this code is triggered only in jest anyway, and we're fairly certain Promise will be available there. hence, the once-off disable for the check

* shorter timers, fix a test, test for Promise

* use global.Promise for existence check

* flush microtasks

* a version that works in browsers (that support postMessage)

I also added a sanity fixture inside fixtures/dom/ mostly for me.

* hoist flushEffectsAndMicroTasks

* pull out tick logic from ReactFiberScheduler

* fix await act (...sync) hanging

- fix a hang when awaiting sync logic
- a better async/await test for test renderer

* feedback changes

- use node's setImmediate if available
- a warning if MessageChannel isn't available
- rename some functions

* pass lint/flow checks (without requiring a Promise polyfill/exclusion)

* prettier

the prettiest, even.

* use globalPromise for the missed await warning

* __DEV__ check for didWarnAboutMessageChannel

* thenables and callbacks instead of promises, pass flow/lint

* tinier. better.

- pulled most bits out of FiberScheduler
- actedUpdates uses callbacks now

* pass build validation

* augh prettier

* golfing 7 more chars

* Test that effects are not flushed without also flushing microtasks

* export doesHavePendingPassiveEffects, nits

* createAct()

* dead code

* missed in merge?

* lose the preflushing bits

* ugh prettier

* removed `actedUpdates()`, created shared/actingUpdatesScopeDepth

* rearrange imports so builds work, remove the hack versions of flushPassiveEffects

* represent actingUpdatesScopeDepth as a tuple [number]

* use a shared flag on React.__SECRET...

* remove createAct, setup act for all relevant renderers

* review feedback

shared/enqueueTask

import ReactSharedInternals from 'shared/ReactSharedInternals';

simpler act() internals

ReactSharedInternals.ReactShouldWarnActingUpdates

* move act() implementation into createReactNoop

* warnIfNotCurrentlyActingUpdatesInDev condition check order
2019-04-02 22:33:31 +01:00
Dominic Gannaway
6a1e6b2f78
Experimental event API: loosen EventTarget constraints and warnings (#15292)
* Remove warning for event targets being direct children of event component

* Addressed feedback and added more test coverage + warnings
2019-04-02 19:49:28 +01:00
Dominic Gannaway
9444a54720
Warn on nested EventTragets in experimental event API (#15287) 2019-04-01 15:47:03 +01:00
Dan Abramov
fb6b50871b Update versions for 16.8.6 2019-03-27 23:58:16 -07:00
Dan Abramov
8e9a013c07 Release 16.8.5 2019-03-22 16:47:59 +00:00
Brian Vaughn
56035dac64
unstable_Profiler -> Profiler (#15172) 2019-03-21 09:18:34 -07:00
Dominic Gannaway
b83e01cade
Adds more scaffolding for experimental event API (#15112)
* Adds more scaffolding for experimental event API
2019-03-20 11:20:17 +00:00
Jared Palmer
2b93d686e3 Add more info to invalid hook call error message (#15139)
* Add more info to invalid hook call error message

* Update other renderers + change call to action

* Update related tests for new hooks error message

* Fix lint errors
2019-03-18 18:22:38 +00:00
Dan Abramov
8d60bd4dc2
[Shallow] Implement setState for Hooks and remount on type change (#15120)
* Throw away old shallow renderer state on type change

This worked in function components but was broken for classes. It incorrectly retained the old instance even if the type was different.

* Remove _previousComponentIdentity

We only needed this because we didn't correctly reset based on type. Now we do so this can go away.

* Use _reset when unmounting

* Use arbitrary componentIdentity

There was no particular reason it was set to element.type. We just wanted to check if something is a render phase update.

* Support Hook state updates in shallow renderer
2019-03-15 22:30:32 +00:00
Brandon Dail
b283d75c17 Support React.memo in ReactShallowRenderer (#14816)
* Support React.memo in ReactShallowRenderer

ReactShallowRenderer uses element.type frequently, but with React.memo
elements the actual type is element.type.type. This updates
ReactShallowRenderer so it uses the correct element type for Memo
components and also validates the inner props for the wrapped
components.

* Allow Rect.memo to prevent re-renders

* Support memo(forwardRef())

* Dont call memo comparison function on initial render

* Fix test

* Small tweaks
2019-03-15 22:17:09 +00:00
Sebastian Silbermann
52c870c8d9 Fix shallow renderer not allowing hooks in forwardRef render functions (#15100)
* test: Add test for shallow + forwardRef + hook

* fix(react-test-renderer): shallow forwardRef hooks
2019-03-15 15:28:34 +00:00
Dominic Gannaway
0c03a47436
Adds experimental event API scaffolding (#15108)
* Adds experimental event API scaffolding
2019-03-14 17:02:42 +00:00
Andrew Clark
1e3b6192b5
Import Scheduler directly, not via host config (#14984)
* Import Scheduler directly, not via host config

We currently schedule asynchronous tasks via the host config. (The host
config is a static/build-time dependency injection system that varies
across different renderers — DOM, native, test, and so on.) Instead of
calling platform APIs like `requestIdleCallback` directly, each renderer
implements a method called `scheduleDeferredCallback`.

We've since discovered that when scheduling tasks, it's crucial that
React work is placed in the same queue as other, non-React work on the
main thread. Otherwise, you easily end up in a starvation scenario where
rendering is constantly interrupted by less important tasks. You need a
centralized coordinator that is used both by React and by other
frameworks and application code. This coordinator must also have a
consistent API across all the different host environments, for
convention's sake and so product code is portable — e.g. so the same
component can work in both React Native and React Native Web.

This turned into the Scheduler package. We will have different builds of
Scheduler for each of our target platforms. With this approach, we treat
Scheduler like a built-in platform primitive that exists wherever React
is supported.

Now that we have this consistent interface, the indirection of the host
config no longer makes sense for the purpose of scheduling tasks. In
fact, we explicitly do not want renderers to scheduled task via any
system except the Scheduler package.

So, this PR removes `scheduleDeferredCallback` and its associated
methods from the host config in favor of directly importing Scheduler.

* Missed an extraneous export
2019-03-06 14:41:45 -08:00
Brian Vaughn
a9aa24ed8d 16.8.4 and changelog 2019-03-05 15:17:42 -08:00
Andrew Clark
69060e1da6
Swap expect(ReactNoop) for expect(Scheduler) (#14971)
* Swap expect(ReactNoop) for expect(Scheduler)

In the previous commits, I upgraded our custom Jest matchers for the
noop and test renderers to use Scheduler under the hood.

Now that all these matchers are using Scheduler, we can drop
support for passing ReactNoop and test roots and always pass
Scheduler directly.

* Externalize Scheduler in noop and test bundles

I also noticed we don't need to regenerator runtime in noop anymore.
2019-02-28 12:54:47 -08:00
Andrew Clark
ccb2a8a44e
Replace test renderer's fake Scheduler implementation with mock build (#14970)
* Replace test renderer's fake Scheduler implementation with mock build

The test renderer has its own mock implementation of the Scheduler
interface, with the ability to partially render work in tests. Now that
this functionality has been lifted into a proper mock Scheduler build,
we can use that instead.

* Fix Profiler tests in prod
2019-02-28 10:50:38 -08:00
Andrew Clark
8e25ed20bd
Unify noop and test renderer assertion APIs (#14952)
* Throw in tests if work is done before emptying log

Test renderer already does this. Makes it harder to miss unexpected
behavior by forcing you to assert on every logged value.

* Convert ReactNoop tests to use jest matchers

The matchers warn if work is flushed while the log is empty. This is
the pattern we already follow for test renderer. I've used the same APIs
as test renderer, so it should be easy to switch between the two.
2019-02-25 19:01:45 -08:00
Dan Abramov
8c1966590a Release 16.8.3 2019-02-21 18:09:18 +00:00
Dan Abramov
3e55560438 Release 16.8.2 2019-02-14 19:13:15 +00:00
Dan Abramov
0e4135e8c2
Revert "[ShallowRenderer] Queue/rerender on dispatched action after render component with hooks (#14802)" (#14839)
This reverts commit 6d4038f0a6.
2019-02-13 16:52:14 +00:00
Rodrigo Ribeiro
6d4038f0a6 [ShallowRenderer] Queue/rerender on dispatched action after render component with hooks (#14802)
* [shallow-renderer] Rerender on dispatched action out of render
2019-02-13 15:59:02 +00:00
Brian Vaughn
45fc46bfa0 16.8.1 packages 2019-02-06 18:21:33 +00:00
Sunil Pai
1107b9673c
[TestUtils.act] warn when using TestUtils.act in node (#14768)
* warn when using TestUtils.act in node

* s/warns/throws

* s/throw/warn

* consistent ellipses
2019-02-06 16:25:26 +00:00
Brian Vaughn
008a2ab9cd 16.8.0 2019-02-06 08:04:00 +00:00
Sunil Pai
d1326f466a
[TestUtils.act] fix return result checking (#14758)
* fix .act return value testing when result === null

* nit
2019-02-05 17:34:21 +00:00
Sunil Pai
267ed98146
expose TestUtils.act() for batching actions in tests (#14744)
* expose unstable_interact for batching actions in tests

* move to TestUtils

* move it all into testutils

* s/interact/act

* warn when calling hook-like setState outside batching mode

* pass tests

* merge-temp

* move jsdom test to callsite

* mark failing tests

* pass most tests (except one)

* augh IE

* pass fuzz tests

* better warning, expose the right batchedUpdates on TestRenderer for www

* move it into hooks, test for dom

* expose a flag on the host config, move stuff around

* rename, pass flow

* pass flow... again

* tweak .act() type

* enable for all jest environments/renderers; pass (most) tests.

* pass all tests

* expose just the warning from the scheduler

* don't return values

* a bunch of changes.

can't return values from .act
don't try to await .act calls
pass tests

* fixes and nits

* "fire events that udpates state"

* nit

* 🙄

* my bad

* hi andrew

(prettier fix)
2019-02-05 16:10:16 +00:00
Andrew Clark
fb3f7bfde9
Avoid importing Scheduler directly (#14757)
* Avoid importing Scheduler directly

The reconciler should not depend directly on Scheduler. This adds it to
the host config for the renderer instead.

(Except for `scheduler/tracing` imports, which are used only by the
profiling build. I've left those imports as-is, though I'm open to
directing those through the host config, too.)

* Make throwaway root id longer to appease Brian
2019-02-05 03:21:25 -08:00
Dan Abramov
c21c41ecfa
Tweak invalid Hook warning and error (#14747) 2019-02-01 21:05:13 +00:00
Andrew Clark
ba6477aa3c
Improve Reducer Hook's lazy init API (#14723)
* Improve Reducer Hook's lazy init API

* Use generic type for initilizer input

Still requires an `any` cast in the case where `init` function is
not provided.
2019-01-29 17:39:24 -08:00
Andrew Clark
cb1ff430e8 Phased dispatcher (#14701)
* Move DEV-only function right above where it's used

I don't like looking at this top-level function #petty

* Use different dispatchers for functions & classes

Classes support readContext, but not any of the other dispatcher
methods. Function support all methods.

This is a more robust version of our previous strategy of checking
whether `currentlyRenderingFiber` is null.

As a next step, we can use a separate dispatcher for each phase of the
render cycle (mount versus update).

* Use separate dispatchers for mount and update

* Remove mount code from update path

Deletes mount-specific code from the update path, since it should be
unreachable. To continue supporting progressive enhancement (mounting
new hooks at the end of the list), we detect when there are no more
current hooks and switch back to the mount dispatcher. Progressive
enhancement isn't officially supported yet, so it will continue to warn.

* Factoring nits

* Fix Flow

Had to cheat more than I would like

* More Flow nits

* Switch back to using a special dispatcher for nested hooks in DEV

In order for this strategy to work, I had to revert progressive
enhancement support (appending hooks to the end). It was previously a
warning but now it results in an error. We'll reconsider later.

* Always pass args to updateState and updateReducer

Even though the extra args are only used on mount, to ensure
type consistency.
2019-01-29 16:32:15 -08:00
Brian Vaughn
6cb26774e2
Enable hooks! (#14679)
* Turned enableHooks feature flag on everywhere
* Removed useHooks feature flag from tests (now that it's on by default)
* Remove useHooks feature flag entirely
2019-01-23 13:28:09 -08:00
Dan Abramov
baa6d40fc8
Mention forwardRef() in <Fn ref={...} /> errors and warnings (#14644) 2019-01-21 16:01:48 +00:00
Grey Baker
b66e6e41e6 Add directory details to the package.json of all packages (#14628)
Specifying the directory as part of the `repository` field in a `package.json`
allows third party tools to provide better support when working with monorepos.
For example, it allows them to correctly construct a commit diff for a specific
package.

This format was accepted by npm in https://github.com/npm/rfcs/pull/19.
2019-01-18 20:21:12 +00:00
Yi-Shan, Chen
4f332885a2 Fix shallow renderer set instance state after gDSFP before calling sCU (#14613)
* Fix shallow renderer set instance state after gDSFP before calling sCU

* Update ReactShallowRenderer.js

* Unwind abstraction

* Fewer names
2019-01-18 02:31:14 +00:00
Dan Abramov
be457ca685
Small tweaks to SSR to match #14594 (#14618)
* Small tweaks to SSR to match #14594

* Remove unnecessary comparison
2019-01-18 00:52:13 +00:00
Dominic Gannaway
4feab7fc92
Add hooks support to ReactShallowRenderer (#14567)
* Add hook support to ReactShallowRenderer
2019-01-17 17:42:27 +00:00
Andrew Clark
c695b2384f React v16.7.0 2018-12-19 17:23:14 -08:00
Brian Vaughn
98eb5ae531
TestRenderer toJSON should not expose the Array wrapper Suspense uses for hidden trees (#14392) 2018-12-05 11:09:51 -08:00
Brian Vaughn
686f1060ad
Publish a local release (canary or stable) to NPM (#14260)
New release scripts.

Learn more at https://github.com/facebook/react/blob/master/scripts/release/README.md
2018-11-23 12:37:18 -08:00