Commit Graph

381 Commits

Author SHA1 Message Date
Dominic Gannaway bd79be9b68 [react-core] Add experimental React Scope component API (#16587) 2019-08-29 12:06:51 +01:00
Luna Ruan f512537754 Babel Transform JSX to React.jsx/React.jsxDEV Plugin (#16432)
This babel transform is a fork of the @babel/plugin-transform-react-jsx transform and is for experimentation purposes only. We don't plan to own this code in the future, and we will upstream this to Babel at some point once we've proven out the concept.

As per the RFC to simplify element creation, we want to change the JSX transform from targeting React.createElement(type, props, children) to React.jsx(type, props, key). This modifies the existing @babel/plugin-transform-react-jsx (and helper) babel plugin to support React.jsx and React.jsxDEV.

The main differences between React.jsx/React.jsxDEV and React.createElement are:
1.) key is now passed as an explicit argument rather than through props
3.) children are now passed through props rather than as an explicit argument
4.) props must always be an object
5.) __source and and __self are now passed as separate arguments into React.jsxDEV rather than through props

Part of the rationale for this change is that we want to deprecate key spread through props because this is an expensive dynamic comparison operation. We want users instead always explicitly pass key as a prop. However, in the interim, we need a way to distinguish between <div {...props} key={foo} /> and <div key={foo} {...props} />. Therefore, until we completely deprecate key spreading, we will use React.createElement to transform <div {...props} key="Hi" /> and React.jsx to transform everything else.
2019-08-27 16:00:20 -07:00
Simen Bekkhus e308a037be chore: make tests compatible with Jest 24 (#15779)
* chore: make tests compatible with Jest 24

* remove fake rafs

* rollback jsdom for localstorage compat

* Apply suggestions from code review

Co-Authored-By: Sunil Pai <threepointone@oculus.com>

* chore: cleanup lockfile
2019-08-14 12:32:26 +01:00
Dan Abramov e0a521b02a Make component stack last argument for deprecation warnings (#16384) 2019-08-13 23:25:03 +01:00
Andrew Clark 0bd0c5269f Upgrade ESLint so we can use JSX Fragment syntax (#16328)
Now that we're using Babel 7, this is the last blocker.
2019-08-09 12:59:02 -07:00
Sebastian Markbåge 07d062dea8 Mark spawned work for client-rendered suspense boundary (#16341)
Currently this is getting marked as Never which is the normal continuation
for a dehydrated boundary, but if it is client-rendered it has a higher
priority. That causes us to drop the interaction tracing for that render.

This colocates the marking where we actually set the expiration time.
2019-08-09 12:37:06 -07:00
Sunil Pai 66a474227b use a different link in the UNSAFE_ component warnings (#16321)
When React detects a deprectated/unsafe lifecycle method, the warning points to a page with more details on the why/what of the warning. However, the actual link (https://fb.me/react-async-component-lifecycle-hooks) uses the phrase "lifecycle-hooks" which is confusing since it doesn't have anything to do with hooks. This PR changes the link to something less confusing - https://fb.me/react-unsafe-component-lifecycles.
2019-08-09 12:18:39 +01:00
lunaruan b12a982062 Babel 7 (#16297)
Upgraded from Babel 6 to Babel 7.

The only significant change seems to be the way `@babel/plugin-transform-classes` handles classes differently from `babel-plugin-transform-es2015-classes`. In regular mode, the former injects a `_createClass` function that increases the bundle size, and in the latter it removes the safeguard checks. However, this is okay because we don't all classes in new features, and we want to deprecate class usage in the future in the react repo.

Co-authored-by: Luna Ruan <luna@fb.com>
Co-authored-by: Abdul Rauf <abdulraufmujahid@gmail.com>
Co-authored-by: Maksim Markelov <maks-markel@mail.ru>
2019-08-08 17:46:35 -07:00
Andrew Clark 85d05b3a4d Bump package.json versions 2019-08-08 14:24:39 -07:00
lunaruan c4f0b93703 Warn when Using String Refs (#16217) 2019-08-07 00:10:19 -07:00
lunaruan c4c9f086eb BugFix: Suspense priority warning firing when not supposed to (#16256)
Previously, the suspense priority warning was fired even if the Root wasn't suspended. Changed the warning to fire only when the root is suspended.

Also refactored the suspense priority warning so it's easier to read.
2019-08-02 13:54:11 -07:00
Dominic Gannaway 42794557ca [Flare] Tweaks to Flare system design and API (#16264) 2019-08-01 19:08:54 +01:00
Sunil Pai 121bfb03bc update legacy context warning message (#16196)
The link in the legacy context message doesn't point to anything context related. This changes the link to point to https://fb.me/react-legacy-context, which points to https://reactjs.org/docs/context.html#legacy-api. Also adds a line that it'll probably be gone later.
2019-07-25 00:34:48 +01:00
Brian Vaughn 9ae5e38f18 Add guard to ensure Profiler onRender prop is function before calling (#16197) 2019-07-24 14:20:56 -07:00
lunaruan 06cc996994 Edit Suspense Priority Warning Message (#16186)
* move 'component that triggered the update' in suspense priority warning message to the beginning of the message

* renamed warnings
2019-07-23 19:08:41 -07:00
Dominic Gannaway 5098891193 [Flare] Redesign core event system (#16163) 2019-07-23 23:46:44 +01:00
lunaruan 03944bfb0b Update Suspense Priority Warning to Include Component that Triggered Update (#16030)
Improved warning whenever lower priority events (ex. data fetching, page load) happen during a high priority update (ex. hover/click events) to include:
1.) Name of component that triggered the high priority update or
2.) Information that the update was triggered on the root
2019-07-22 14:17:43 -07:00
Dominic Gannaway 2c4d61e102 Adds experimental fundamental interface (#16049) 2019-07-19 22:20:28 +01:00
Sunil Pai d9b4c55d53 unify deprecated/unsafe lifecycle warnings, pass tests (#16103)
- redoes #15431 from scratch, taking on the feedback there
- unifies the messaging between "deprecated" and UNSAFE_ lifecycle messages. It reorganizes ReactStrictModeWarnings.js to capture and flush all the lifecycle warnings in one procedure each.
- matches the warning from ReactPartialRenderer to match the above change
- passes all the tests
- this also turns on `warnAboutDeprecatedLifecycles` for the test renderer. I think we missed doing so it previously. In a future PR, I'll remove the feature flag altogether.
- this DOES NOT do the same treatment for context warnings, I'll do that in another PR too
2019-07-15 20:56:44 +01:00
Brian Vaughn 8d413bf2c3 Remove React.error and React.warn (#16126)
* Remove React.error/React.warn with React.getComponentStack
2019-07-12 15:41:47 -07:00
Sunil Pai 3f1dee09a4 expose act() sigil correctly for umd builds (#16110)
after https://github.com/facebook/react/pull/16039, act was broken for umd builds. This PR fixes it.
2019-07-11 14:56:03 +01:00
Dominic Gannaway 67e3f3fb6e [Flare] Revise responder event types (#16081) 2019-07-08 14:35:59 +01:00
Min ho Kim 2a0f6390ed Fix typos (#16076) 2019-07-08 11:51:29 +01:00
Sunil Pai a457e02ae3 allow nested act()s from different renderers (#16039)
* allow nested `act()`s from different renderers

There are usecases where multiple renderers need to oprate inside an act() scope
- ReactDOM.render being used inside another component tree. The parent component will be rendered using ReactTestRenderer.create for a snapshot test or something.
- a ReactDOM instance interacting with a ReactTestRenderer instance (like for the new devtools)

This PR changes the way the acting sigils operate to allow for this. It keeps 2 booleans, one attached to React, one attached to the renderer. act() changes these values, and the workloop reads them to decide what warning to trigger.

I also renamed shouldWarnUnactedUpdates to warnsIfNotActing

* s/ReactIsActing/IsSomeRendererActing and s/ReactRendererIsActing/IsThisRendererActing
2019-07-02 22:20:17 +01:00
Dominic Gannaway 9b0bd43550 [Flare] Re-label Flare flag (#16014) 2019-06-28 01:11:11 +01:00
Andrew Clark 4d307de458 Prefix mock Scheduler APIs with _unstable (#15999)
For now this is only meant to be consumed via `act`.
2019-06-26 12:16:08 -07:00
Sunil Pai 04b77c6304 followup to #15763, fix failing test in ReactDOMTracing-test (#15972)
* followup to #15763, failing tests in ReactDOMTracing-test

It was me. I broke the build.

* [ignore] add a newline to trigger a build
2019-06-24 11:44:37 +01:00
Sunil Pai e1c5e8720d warn if passive effects get queued outside of an act() call. (#15763)
* warn if passive effects get queued outside of an act() call

While the code itself isn't much (it adds the warning to mountEffect() and updateEffect() in ReactFiberHooks), it does change a lot of our tests. We follow a bad-ish pattern here, which is doing asserts inside act() scopes, but it makes sense for *us* because we're testing intermediate states, and we're manually flush/yield what we need in these tests.

This commit has one last failing test. Working on it.

* pass lint

* pass failing test, fixes another

- a test was failing in ReactDOMServerIntegrationHooks while testing an effect; the behaviour of yields was different from browser and server when wrapped with act(). further, because of how we initialized modules, act() around renders wasn't working corrrectly. solved by passing in ReactTestUtils in initModules, and checking on the finally yielded values in the specific test.
- in ReactUpdates, while testing an infinite recursion detection, the test needed to be wrapped in an act(), which would have caused the recusrsion error to throw. solived by rethrowing the error from inside the act().

* pass ReactDOMServerSuspense

* stray todo

* a better message, consistent with the state update one.
2019-06-24 11:18:24 +01:00
Sebastian Markbåge d77d12510b Expire rendering the tail of SuspenseList after a timeout (#15946)
* Expire rendering the tail of SuspenseList after a timeout

This is the first Suspense feature that isn't actually dependent on IO.

The thinking here is that it's normal for a SuspenseList to show loading
states, and it'll be designed to handle it one at a time.

However, sometimes there are lists with really big items that take a long
time to CPU render. Since data can become available as we do that, it is
likely that we have all the data and become CPU bound.

In that case, the list would naively just render until the end and then
display all items at once. I think that's actually what you want for fast
lists. However, for slow ones (like News Feed), you're better off showing
a few rows at a time.

It's not necessarily one at a time because if you can do many in a short
period of time and fit them all on the screen, then it's better to do them
all at once than pop them in one at a time very quickly.

Therefore, I use a heuristic of trying to render as many rows as I can in
500ms before giving up.

This timer starts before the first row of the tail and we only check it
after. This ensures that we always make a little progress each attempt.
An alternative approach could be to start the time before doing the head
of the list but we don't want that being slow prevent us from making
further progress.

Currently, I disable this optimization at Never priority because there's
nothing intermediate that becomes visible anyway.

* Fix tracing through a SuspenseList

This ensures that we can spawn new work during render through arbitrary
priorities.

We'll need this for other features too.

Since each priority can commit separately we need to use an array to
include the current interactions on each priority.
2019-06-21 18:05:34 -07:00
Dominic Gannaway dc298fdf91 [Flare] Refinements to useEvent hook (#15955) 2019-06-21 23:10:55 +01:00
Dominic Gannaway 34ce57ae75 [Flare] Refine flow type annotations (#15950) 2019-06-21 12:32:43 +01:00
Dominic Gannaway 4f92fbce5c [Flare] Move createEvent back to React object (#15943) 2019-06-21 10:12:56 +01:00
Dominic Gannaway 720db4cbe6 [Flare] Add useEvent hook implementation (#15927)
* [Flare] Add useEvent hook implementation

Validate hooks have decendent event components

Few fixes and displayName changes

Fix more responder bugs

Update error codes

* Add another test

* Address feedback
2019-06-20 19:12:40 -07:00
Sebastian Markbåge 76864f7ff7 Add SuspenseList Component (#15902)
* Add SuspenseList component type

* Push SuspenseContext for SuspenseList

* Force Suspense boundaries into their fallback state

In the "together" mode, we do a second render pass that forces the
fallbacks to stay in place, if not all can unsuspend at once.

* Add test

* Transfer thennables to the SuspenseList

This way, we end up retrying the SuspenseList in case the nested boundary
that just suspended doesn't actually get mounted with this set of
thennables. This happens when the second pass renders the fallback
directly without first attempting to render the content.

* Add warning for unsupported displayOrder

* Add tests for nested sibling boundaries and nested lists

* Fix nested SuspenseList forwarding thennables

* Rename displayOrder to revealOrder

Display order has some "display list" connotations making it sound like
a z-index thing.

Reveal indicates that this isn't really about when something gets rendered
or is ready to be rendered. It's about when content that is already there
gets to be revealed.

* Add test for avoided boundaries

* Make SuspenseList a noop in legacy mode

* Use an explicit suspense list state object

This will be used for more things in the directional case.
2019-06-19 19:34:28 -07:00
Dominic Gannaway 689beef6f5 [Flare] Move unstable_createEventComponent to ReactDOM (#15890) 2019-06-18 23:41:00 +01:00
Brian Vaughn 801feed95c Interaction tracing works across hidden and SSR hydration boundaries (#15872)
* Interaction tracing works across hidden and SSR hydration boundaries
2019-06-14 18:08:23 -07:00
Dominic Gannaway 8cfcfe0fcb [Flare] Fix ES6 issues with IE11 (#15834) 2019-06-06 18:38:46 +01:00
Sebastian Markbåge 113497cc0e [Suspense] Change Suspending and Restarting Heuristics (#15769)
* Track most recent commit time of a fallback globally

This value is going to be used to avoid committing too many fallback
states in quick succession. It doesn't really matter where in the tree
that happened.

This means that we now don't really need the concept of SuspenseState
other than has a flag. It could be made cheaper/simpler.

* Change suspense heuristic

This now eagerly commits non-delayed suspended trees, unless they're
only retries in which case they're throttled to 500ms.

* Restart early if we're going to suspend later

* Use the local variable where appropriate

* Make ReactLazy tests less specific on asserting intermediate states

They're not testing the exact states of the suspense boundaries, only
the result. I keep assertions that they're not already resolved early.

* Adjust Profiler tests to the new heuristics

* Update snapshot tests for user timing tests

I also added a blank initial render to ensuree that we cover the suspended
case.

* Adjust Suspense tests to account for new heuristics

Mostly this just means render the Suspense boundary first so that it
becomes an update instead of initial mount.

* Track whether we have a ping on the currently rendering level

If we get a ping on this level but have not yet suspended, we might
still suspend later. In that case we should still restart.

* Add comment about moving markers

We should add this to throwException so we get these markers earlier.
I've had to rewrite tests that test restarting to account for the delayed
restarting heuristic.

Ideally, we should also be able to restart from within throwException if
we're already ready to restart. Right now we wait until the next yield.

* Add test for restarting during throttled retry

* Add test that we don't restart for initial render

* Add Suspense Heuristics as a comment in Throw
2019-05-30 16:37:56 -07:00
Sunil Pai 9aad17d60c using the wrong renderer's act() should warn (#15756)
* warn when using the wrong renderer's act around another renderer's updates

like it says. it uses a real object as the sigil (instead of just a boolean). specifically, it uses a renderer's flushPassiveEffects as the sigil. We also run tests for this separate from our main suite (which doesn't allow loading multiple renderers in a suite), but makes sure to run this in CI as well.

* unneeded (and wrong) comment

* run the dom fixture on CI

* update the sigil only in __DEV__

* remove the obnoxious comment

* use an explicit export for the sigil
2019-05-29 22:56:04 +01:00
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
Andrew Clark 83fc258f29 Remove <ConcurrentMode /> (#15532)
Use createSyncRoot instead.
2019-05-13 16:10:00 -07:00
Andrew Clark edfedf3ae9 Fork ReactSharedInternals for UMD builds (#15617) 2019-05-10 13:51:39 -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
Nicolas Gallagher 89d8d1435f Add React.unstable_createEventComponent (#15580)
API for creating event components from event responders.
2019-05-07 12:36:42 -07:00
Andrew Clark 72ca3c60e7 Bump scheduler version to 0.14.0 (#15395) 2019-04-29 18:10:11 -07:00
Brian Vaughn 1b752f1914 Fixed potential interaction tracing leak in Suspense thennable memoization (#15531)
Audited the other places we call unstable_wrap() in React DOM and verified that they didn't have this similar problem.
2019-04-29 15:04:52 -07:00
Andrew Clark 9055e31e5c Replace old Fiber Scheduler with new one (#15387)
The new Fiber Scheduler has been running in Facebook for several days
without issues. Let's switch to it.
2019-04-11 19:15:34 -07:00
Ricky Vetter 745baf2e06 Provide new jsx transform target for reactjs/rfcs#107 (#15141)
* adding jsx function

* add more feature flag defaults

* flip ReactElement order back
2019-04-07 15:02:34 -04: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