Commit Graph

10973 Commits

Author SHA1 Message Date
Dominic Gannaway
287ef30bba [Flare] Deeply prevent default on anchor elements (#15750) 2019-05-28 12:46:07 +01:00
Dominic Gannaway
a97b5c07b0 [Flare] More fixes for getAbsoluteBoundingClientRect (#15746) 2019-05-27 19:03:40 +01:00
Andrew Clark
5fe97dbe19 Remove sizebot race condition (#15735)
Sometimes the status of the `build` job is not in the first page of
the `/statuses` endpoint. The combined `/status` endpoint consolidates
the entries, though, so it always appears there.
2019-05-24 18:55:28 -07:00
Dan Abramov
393924879f [Fresh] Babel plugin now handles HOCs + add integration tests (#15724)
* Refactor component search to prepare for deeper traversals

* Register HOCs with intermediate results

* Register components that are used as JSX types

* Add integration test skeleton

The integration test combines testing runtime together with the Babel plugin. It's a bit harder to debug because multiple things can go wrong, but it helps us build confidence that specific scenarios work well.

* Add HOC integration test and fix conflict with JSX transform

* Infer usage from createElement too

This helps us avoid dependency on the plugin order.

* Remove outdated comments

* Wrap tests in __DEV__

* Support export default hoc(...) for anonymous functions

* Fix test indentation

* Fix comment typo

* Use named function for test as this case is more important
2019-05-25 00:45:08 +04:00
Andrew Clark
2b58797365 Typo in CircleCI config 2019-05-23 15:33:56 -07:00
Sebastian Markbåge
8af1f87929 Rename ReactFiberScheduler -> ReactFiberWorkLoop and extract throwException from Unwind (#15725)
* Rename ReactFiberScheduler to ReactFiberWorkLoop

The scheduling part is mostly extracted out to the scheduler package.

What's remaining is mostly around the loop around each section of work.
I name it something with Work in it because it's very related to the
BeginWork, CompleteWork and UnwindWork sections.

* Extract throwException from UnwindWork

Our throwing works more like algebraic effects in that it's a separate
phase where we find a handler and we later unwind.
2019-05-23 14:24:18 -07:00
Andrew Clark
399cd0d16c Set up cron job to run fuzz tester (#15718)
Sets up a CircleCI workflow to run the fuzz tests with a randomly
generated seed. The workflow runs on an hourly schedule.
2019-05-23 14:09:08 -07:00
Dominic Gannaway
025b07b610 [Flare] Ensure getAbsoluteBoundingClientRect aligns with offsetParent (#15720) 2019-05-23 13:51:14 +01:00
James Ide
61f62246c8 [react-native] Use path-based imports instead of Haste for the RN renderer (#15604)
* [react-native] Use path-based imports instead of Haste for the RN renderer

To move React Native to standard path-based imports instead of Haste, the RN renderer that is generated from the code in this repo needs to use path-based imports as well since the generated code is vendored by RN. This commit makes it so the interface between the generated renderers and RN does not rely on Haste and instead uses a private interface explicitly defined by RN. This inverts control of the abstraction so that RN decides the internals to export rather than React deciding what to import.

On RN's side, a new module named `react-native/Libraries/ReactPrivate/ReactNativePrivateInterface` explicitly exports the modules used by the renderers in this repo. (There is also a private module for InitializeCore so that we can import it just for the side effects.) On React's side, the various renderer modules access RN internals through the explicit private interface.

The Rollup configuration becomes slimmer since the only external package is now `react-native`, and the individual modules are instead listed out in `ReactNativePrivateInterface`.

Task description: https://github.com/facebook/react-native/issues/24770
Sister RN PR (needs to land before this one): https://github.com/facebook/react-native/pull/24782

Test Plan: Ran unit tests and Flow in this repo. Generated the renderers and manually copied them over to the RN repo. Ran the RN tests and launched the RNTester app.

* Access natively defined "nativeFabricUIManager" instead of importing it

Some places in the Fabric renderers access `nativeFabricUIManager` (a natively defined global) instead of importing UIManager. While this is coupling across repos that depends on the timing of events, it is necessary until we have a way to defer top-level imports to run after `nativeFabricUIManager` is defined. So for consistency we use `nativeFabricUIManager` everywhere (see the comment in https://github.com/facebook/react/pull/15604#pullrequestreview-236842223 for more context).
2019-05-23 08:23:54 +01:00
Dominic Gannaway
b962adfc2b [Flare] event component displayName is now mandatory (#15717) 2019-05-23 01:29:07 +01:00
Andrew Clark
d66c8f2d9d Update sizebot to match name of CircleCI build job (#15714)
The sizebot scrapes the GitHub `/statuses` endpoint to get the lastest
CircleCI build number for master, in order to fetch the bundle size
info for that build, which are stored as build artifacts. (There's gotta
be a better way to do this, but that's what we have for now.) This
updates the script to match the name of the updated CircleCI job that
generates the bundle sizes.
2019-05-22 16:12:14 -07:00
Dan Abramov
5c2124fc76 [Fresh] Initial Babel plugin implementation (#15711)
* Add initial Babel plugin implementation

* Register exported functions

* Fix missing declarations

Always declare them at the bottom and rely on hoisting.

* Remove unused code

* Don't pass filename to tests

I've decided for now that the plugin doesn't need filename, and it will be handled by module runtime integration instead.

* Fix bugs

* Coalesce variable declarations
2019-05-22 23:11:09 +01:00
Andrew Clark
101901dc2d Remove redundant test run (#15713) 2019-05-22 13:50:43 -07:00
Andrew Clark
1c0bdb710d Always run yarn after restoring modules cache (#15712) 2019-05-22 13:33:33 -07:00
Dominic Gannaway
b9ebc37c5b Fix Flow (#15710) 2019-05-22 21:04:28 +01:00
Dominic Gannaway
a25a793fe9 [Flare] update getEventCurrentTarget to use fiber tree (#15708) 2019-05-22 19:59:00 +01:00
Dominic Gannaway
b5dff62faf [Flare] Account for fixed elements in getAbsoluteBoundingClientRect (#15707) 2019-05-22 19:54:08 +01:00
Andrew Clark
f3109ad8a7 Parallelize CircleCI jobs using workflows (#15704)
Updates the CircleCI config to use the workflows features to run jobs in
parallel, instead of the `parallelism` option. This change alone doesn't
improve the overall build time much, since almost all of the total time
is spent running the Rollup script, which runs entirely sequentially.
But it does improve reporting, and should make it easier to add
additional parallel jobs in the future.
2019-05-22 11:14:14 -07:00
Maksim Markelov
f50f9ba5db Fix ReactFiberNewContext spelling (#15692) 2019-05-22 11:24:31 +01:00
Dominic Gannaway
e180f656f3 Flare: change flushDiscreteUpdates invariant to warning (#15702) 2019-05-22 01:09:34 +01:00
Andrew Clark
7829d8cf99 Fix missing return pointer assignment (#15700)
* Fix missing return pointer assignment

I found a bug using the fuzz tester that manifested as incorrect
ordering of children in the host tree, but whose root cause was a
missing `return` pointer assignment on a work-in-progress fiber.

Usually return pointers are set during reconciliation
(`reconcileChildFibers`) but this particular assignment happens inside
the custom reconciliation implementation used by Suspense boundaries.

I would not be surprised if there were similar bugs related to incorrect
return pointers. You're supposed to update the return pointer
whenever a work-in-progress fiber is created, but there's nothing in
the contract of the `createFiber` or `createWorkInProgress` function
that implies this. I propose that we update their signatures to accept
the return fiber as an argument. I will do this in a follow-up.

In this commit, I rearranged `updateSuspenseComponent` slightly so that
every call to `createWorkInProgress` or a `createFiber*` function is
immediately followed by a return pointer assignment.

I hardcoded the fuzz test case that surfaced the bug.

* Update all progressed children in list

`progressedPrimaryChild` is a list, not a single fiber. Need to iterate
through every child and update their return pointers.
2019-05-21 16:56:52 -07:00
Sebastian Markbåge
d7afe23f14 Rename "loading" to "busy" in SuspenseConfig API (#15699)
loadingDelayMs -> busyDelayMs
minLoadingDurationMs -> busyMinDurationMs
2019-05-21 14:29:41 -07:00
Dominic Gannaway
ef4ac42f88 [Flare] Update interactiveUpdates flushing heuristics (#15687) 2019-05-21 22:03:45 +01:00
Dan Abramov
6d4f85b611 [Fresh] Set up infra for runtime and Babel plugin (#15698)
* Add a stub for React Fresh Babel plugin package

* Move ReactFresh-test into ReactFresh top level directory

* Add a stub for React Fresh Runtime entry point

* Extract Fresh runtime from tests into its entry point
2019-05-21 21:54:10 +01:00
Dominic Gannaway
121acae090 Flare: simplify dispatchEvent discrete argument (#15694) 2019-05-21 16:06:17 +01:00
Dominic Gannaway
a398cbd5a7 Flare: update invalid accessor warnings + add no-ops (#15693) 2019-05-21 14:12:19 +01:00
Sunil Pai
9c9ea94852 flush only on exiting outermost act() (#15682) 2019-05-21 10:41:24 +01:00
Brian Vaughn
50b50c26f6 Inform DevTools of commit priority level (#15664)
* Pass inferred priority level to DevTools commit hook in PROFILE mode
2019-05-20 08:37:25 -07:00
Dan Abramov
0bd9b5d006 [Fresh] Support re-rendering lazy() without losing state (#15686)
* Support re-rendering lazy() without losing state

* Clearer naming
2019-05-20 15:47:27 +01:00
Dan Abramov
ec38def44f [Fresh] Don't traverse remounted trees (#15685)
* Don't traverse children when hot reloading needs a remount

If we're gonna remount that tree anyway, there is no use in traversing its children beforehand.

* Add a test verifying hot reload batches updates

Otherwise there is a risk of it being super slow due to cascades.
2019-05-20 14:55:01 +01:00
Dan Abramov
5731e522d4 [Fresh] Support lazy() and add Suspense tests (#15681)
* Test that state is not leaked between components

* Support lazy and add Suspense tests

* Nits
2019-05-20 14:11:18 +01:00
Dan Abramov
31487dd82e [Fresh] Set up initial scaffolding (#15619)
* Add a minimal failing test for hot reload

* Set up scaffolding for React Fresh

* Consider type family when comparing elementType

Rendering an element with stale type should not cause it to remount.

We only do this for FunctionComponent tag since checking is unnecessary for classes or host components.

* Add support for forwardRef()

Initially I thought I would compare families of inner .render functions.

However, there is a corner case where this can create false positives. Such as when you forwardRef(X) the same X twice. Those are supposed to be distinct. But if we compare .render functions, we wouldn't be able to distinguish them after first reload.

It seems safer to rely on explicit registration for those. This should be easy when forwardRef() call is in the same file, and usually it would be. For cases like HOCs and style.div`...` factories that return forwardRef(), we could have the __register__ helper itself "dig deeper" and register the inner function.

* Show how forwardRef inner identity can be inferred

The __register__ implementation can read the inner identity itself.

* Add missing __DEV__ to tests

* Add support for memo() (without fixing bailouts)

This adds rudimentary support for memo components. However, we don't actually skip bailouts yet, so this is not very useful by itself alone. Tests have TODOs that we need to remove after bailout skipping is done.

* Refactor type comparison for clarity

* Hot update shouldn't re-render ancestor components unnecessarily

My code had a bug where it checked for a wrong thing in a wrong set, leading us to always re-render.

This fixes the checks so that we only schedule updates for things that were actually edited.

* Add test coverage for memo(fn, areEqual)

* Explicitly skip bailouts for hot reloading fibers

This forces even memo() with shallow comparison to re-render on hot update.

* Refactor scheduling update to reduce duplication

* Remove unused variable in test

* Don't check presence in a set while not hot reloading

* Make scheduleHotUpdate() take named arguments

* Don't keep unedited component types in the type => family map

It's unnecessary because if they haven't been edited, there's no special reconciliation logic.

* Add signatures that force remounting

Signatures let us force a remount of a type even if from React's point of view, type is the same.

A type has one current signature. If that signature changes during next hot update, all Fibers with that type should be deleted and remounted.

We do this by mutating elementType scheduling a parent.

This will be handy to force remount of mismatching Hooks, as well as failed error boundaries.

For this to fully work, we'll need to add a way to skip built-in bailouts for all Fiber types. This will be the most invasive and annoying change. I did it for HostRoot in this PR but there's more. I'll add an automated test case that catches the missing bailout bailouts.

* Support forced remounting for all component types

This teaches all parent component types to remount their child if necessary.

It also adds tests for them.

* Remount effects while preserving state for hot reloaded components

This makes sure that changes to *code* always propagate.

It can break components that aren't resilient to useEffect over-firing, but that seems like a good constraint since you might need to add a dependency later anyway, and this helps avoid coding yourself into the corner.

* Add missing __DEV__ blocks to tests

* Fix unused variables in tests

* Remove outdated TODO

* Expose scheduleHotUpdate directly

* Inline isCompatibleType

* Run one check per component for invalidating deps

This also makes the bailouts more targeted--no need to remount useEffect for a parent component of remounted fiber.

* Resolve .type early

This moves resolving to set up the right .type early instead of doing this before render.
A bit more future-proof in case we want to restructure the begin phase later.

ForwardRef is special because its type is a wrapper but it can be hot reloaded by itself.
So we have a special overload for it that reconstucts the wrapper type if needed.

* Add a Suspense todo

* Use current.type !== workInProgress.type for ignoring deps

This gets rid of one of the sets.

* Use workInProgress.type !== current.type check for force re-render

We still use a set for forced remount though.

* Use wip.type !== current.type check in more places

This also disables the remounting tests. They need a separate approach.

* Use a dedicated remount mechanism

* Add a test for offscreen trees

It has a TODO because it seems like offscreen updates are incorrectly applied too soon.

* Enable offscreen test now that it is fixed

* Fix corner cases in the new remounting mechanism

* Remount failed error boundaries on hot reload

* Fix test now that act() flushes

This test is manual so I don't actually want act here.

* Nits

* Add comments
2019-05-18 01:38:13 +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
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
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
Dominic Gannaway
af19e2eb2f Event API: adds pointerType to Focus events (#15645) 2019-05-14 15:59:36 +01: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
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