Compare commits

...

1881 Commits

Author SHA1 Message Date
Brian Vaughn
5faf377df5 Fixed a style bug in props editor (#17162) 2019-10-21 15:08:55 -07:00
Dominic Gannaway
f7ec65eeba [react-interactions] Make events non-passive to allow preventDefault (#17136) 2019-10-21 22:37:27 +02:00
Andrew Clark
1022ee0ec1 Read current time without marking event start time (#17160)
* Failing test: DevTools hook freezes timeline

The DevTools hook calls `requestCurrentTime` after the commit phase has
ended, which has the accidnental consequence of freezing the start
time for subsequent updates. If enough time goes by, the next update
will instantly expire.

I'll push a fix in the next commit.

* Read current time without marking event start time

`requestCurrentTime` is only meant to be used for updates, because
subsequent calls within the same event will receive the same time.
Messing this up has bad consequences.

I renamed it to `requestCurrentTimeForUpdate` and created a new
function that returns the current time without the batching heuristic,
called `getCurrentTime`.

Swapping `requestCurrentTime` for `getCurrentTime` in the DevTools
hook fixes the regression test added in the previous commit.
2019-10-21 13:15:37 -07:00
Andrew Clark
349cf5acc3 Experimental test helper: it.experimental (#17149)
Special version of Jest's `it` for experimental tests. Tests marked as
experimental will run **both** stable and experimental modes. In
experimental mode, they work the same as the normal Jest methods. In
stable mode, they are **expected to fail**. This means we can detect
when a test previously marked as experimental can be un-marked when the
feature becomes stable. It also reduces the chances that we accidentally
add experimental APIs to the stable builds before we intend.

I added corresponding methods for the focus and skip APIs:

- `fit` -> `fit.experimental`
- `it.only` -> `it.only.experimental` or `it.experimental.only`
- `xit` -> `xit.experimental`
- `it.skip` -> `it.skip.experimental` or `it.experimental.skip`

Since `it` is an alias of `test`, `test.experimental` works, too.
2019-10-19 16:08:08 -07:00
Andrew Clark
edc234c730 Build script should default to experimental (#17144)
`yarn build` defaults to building in experimental mode. To opt-out, set
the `RELEASE_CHANNEL` environment variable to `stable`. This is the same
as what we do when running tests via `yarn test`, to make local
development easier.
2019-10-18 19:35:33 -07:00
Sebastian Markbåge
3cc564547c SuspenseList support in DevTools (#17145)
* SuspenseList support in DevTools

This adds SuspenseList tags to DevTools so that the name properly shows
up.

It also switches to use the tag instead of Symbol type for Suspense
components. We shouldn't rely on the type for any built-ins since that
field will disappear from the fibers. How the Fibers get created is an
implementation detail that can change e.g. with a compiler or if we
use instanceof checks that are faster than symbol comparisons.

* Add SuspenseList test to shell app
2019-10-18 17:18:36 -07:00
Sebastian Markbåge
68fb58029d Remove unstable_ prefix in various internal uses (#17146)
* Rename unstable_createRoot in DevTools

* Rename createSyncRoot in warning
2019-10-18 17:18:10 -07:00
Andrew Clark
3059ab3523 Add experimental instructions to release README (#17143) 2019-10-18 16:26:06 -07:00
Andrew Clark
093de5fb43 Lint experimental build artifacts (#17141)
Adds `lint_build` job to the experimental workflow
2019-10-18 16:03:08 -07:00
Andrew Clark
7082d5a2db Don't build non-experimental www bundles (#17139)
Reduces the likelihood we'll accidentally sync the wrong ones.
2019-10-18 14:36:59 -07:00
Andrew Clark
c47f59331e Move SuspenseList to experimental package (#17130)
Also moves `withSuspenseConfig`
2019-10-18 14:24:13 -07:00
Luna Ruan
685ed561f2 Migrate useDeferredValue and useTransition (#17058)
Migrated useDeferredValue and useTransition from Facebook's www repo into ReactFiberHooks.
2019-10-18 12:48:43 -07:00
Dan Abramov
0b61e26983 Update RN typings for a shim (#17138) 2019-10-18 18:05:09 +01:00
Sebastian Markbåge
4eeee358e1 [SuspenseList] Store lastEffect before rendering (#17131)
* Add a failing test for SuspenseList bug

* Store lastEffect before rendering

We can't reset the effect list to null because we don't rereconcile the
children so we drop deletion effects if we do that.

Instead we store the last effect as it was before we started rendering
so we can go back to where it was when we reset it.

We actually already do something like this when we delete the last row
for the tail="hidden" mode so we had a field available for it already.
2019-10-17 15:57:07 -07:00
Nicolas Gallagher
4fb5bf61dd [react-interactions] Fix focus-visible heuristic (#17124)
Respond to all keys not just `Tab`
2019-10-17 09:24:31 -07:00
Dominic Gannaway
8facc05373 [react-interactions] Allow event.preventDefault on LegacyPress responder (#17113)
[react-interactions] Allow event.preventDefault on LegacyPress responder
2019-10-17 10:21:02 +02:00
Andrew Clark
7cec15155a Remove prefixed concurrent APIs from www build (#17108)
The downstream callers have been updated, so we can remove these.
2019-10-16 18:58:33 -07:00
Sebastian Markbåge
ed5f010ae5 Client render Suspense content if there's no boundary match (#16945)
Without the enableSuspenseServerRenderer flag there will never be a boundary match. Also when it is enabled, there might not be a boundary match if something was conditionally rendered by mistake.

With this PR it will now client render the content of a Suspense boundary in that case and issue a DEV only hydration warning. This is the only sound semantics for this case.

Unfortunately, landing this will once again break #16938. It will be less bad though because at least it'll just work by client rendering the content instead of hydrating and issue a DEV only warning.

However, we must land this before enabling the enableSuspenseServerRenderer flag since it does this anyway.

I did notice that we special case fallback={undefined} due to our unfortunate semantics for that. So technically a workaround that works is actually setting the fallback to undefined on the server and during hydration. Then flip it on only after hydration. That could be a workaround if you want to be able to have a Suspense boundary work only after hydration for some reason.

It's kind of unfortunate but at least those semantics are internally consistent. So I added a test for that.
2019-10-16 16:23:12 -07:00
Dominic Gannaway
916937563b [react-interactions] Add onFocusWithin event to FocusWithin responder (#17115) 2019-10-16 22:57:08 +02:00
Andrew Clark
d7feeb25ac unstable_createRoot -> createRoot in test (#17107)
Fixes test added in #17105, which was based on an earler commit than the
one that removed the `unstable_` prefix from `createRoot`.
2019-10-15 21:37:54 -07:00
Sebastian Markbåge
6ff23f2a5d Change retry priority to "Never" for dehydrated boundaries (#17105)
This changes the "default" retryTime to NoWork which schedules at Normal
pri.

Dehydrated bouundaries normally hydrate at Never priority except when they
retry where we accidentally increased them to Normal because Never was used
as the default value. This changes it so NoWork is the default.

Dehydrated boundaries however get initialized to Never as the default.

Therefore they now hydrate as Never pri unless their priority gets
increased by a forced rerender or selective hydration.

This revealed that erroring at this Never priority can cause an infinite
rerender. So I fixed that too.
2019-10-15 19:53:20 -07:00
Andrew Clark
2c832b4dcf Separate sizebot for experimental builds (#17100)
Configures the sizebot to leave a second comment that tracks the
experimental build artifacts.
2019-10-15 18:43:06 -07:00
Luna Ruan
3ac0eb075d Modify Babel React JSX Duplicate Children Fix (#17101)
If a JSX element has both a children prop and children (ie. <div children={childOne}>{childTwo}</div>), IE throws an Multiple definitions of a property not allowed in strict mode. This modifies the previous fix (which used an Object.assign) by making the duplicate children a sequence expression on the next prop/child instead so that ordering is preserved. For example:

```
<Component children={useA()} foo={useB()} children={useC()}>{useD()}</Component>
```
should compile to
```
React.jsx(Component, {foo: (useA(), useB()), children: (useC(), useD)})
```
2019-10-15 17:13:21 -07:00
Andrew Clark
43562455c9 Temporary patch www fork with prefixed APIs (#17103)
I'm doing this here instead of in the downstream repo so that if the
sync diff gets reverted, it doesn't revert this, too.

Once the sync has landed, and the callers are updated in www, I will
remove this.
2019-10-15 16:44:33 -07:00
Andrew Clark
9123c479f4 Enable concurrent APIs in all experimental forks (#17102)
Forgot to update the flags in the forked modules.
2019-10-15 16:19:45 -07:00
Andrew Clark
30c5daf943 Remove concurrent apis from stable (#17088)
* Tests run in experimental mode by default

For local development, you usually want experiments enabled. Unless
the release channel is set with an environment variable, tests will
run with __EXPERIMENTAL__ set to `true`.

* Remove concurrent APIs from stable builds

Those who want to try concurrent mode should use the experimental
builds instead.

I've left the `unstable_` prefixed APIs in the Facebook build so we
can continue experimenting with them internally without blessing them
for widespread use.

* Turn on SSR flags in experimental build

* Remove prefixed concurrent APIs from www build

Instead we'll use the experimental builds when syncing to www.

* Remove "canary" from internal React version string
2019-10-15 15:09:19 -07:00
Dominic Gannaway
4cb399a433 [react-interactions] Modify Scope query mechanism (#17095) 2019-10-15 15:57:02 +02:00
Dominic Gannaway
e7704e22a1 [babel-plugin-react-jsx] Avoid duplicate "children" key in props object (#17094)
* [babel-plugin-react-jsx] Avoid duplicate "children" key in props object

* Use Object.assign approach
2019-10-15 15:41:09 +02:00
Krzysztof Kotowicz
fdba0e5ce7 Fixed a bug with illegal invocation for Trusted Types (#17083)
* Fixed a bug with illegal invocation.

* Fixed the test.
2019-10-15 11:41:42 +01:00
Andrew Clark
a8c6a1b34e Update release scripts to support experimental releases (#17086)
* Download correct artifacts for release channel

Experimental builds should pull artifacts from the
`process_artifacts_experimental` job.

I think instead of two separate CI workflows, a better approach might
be to build stable artifacts to the `build` directory and the
experimental artifacts to a `build_experimental` directory, and
generate both within the same workflow. This would take some work since
lots of things assume the output directory is `build`, but something
to consider in the future.

* Prevent experimental promotion to stable

Adds a check to the `prepare-stable` script to prevent experimental
builds from being published using stable semver versions.
2019-10-14 14:15:23 -07:00
Andrew Clark
d364d8555f Set up experimental builds (#17071)
* Don't bother including `unstable_` in error

The method names don't get stripped out of the production bundles
because they are passed as arguments to the error decoder.

Let's just always use the unprefixed APIs in the messages.

* Set up experimental builds

The experimental builds are packaged exactly like builds in the stable
release channel: same file structure, entry points, and npm package
names. The goal is to match what will eventually be released in stable
as closely as possible, but with additional features turned on.

Versioning and Releasing
------------------------

The experimental builds will be published to the same registry and
package names as the stable ones. However, they will be versioned using
a separate scheme. Instead of semver versions, experimental releases
will receive arbitrary version strings based on their content hashes.
The motivation is to thwart attempts to use a version range to match
against future experimental releases. The only way to install or depend
on an experimental release is to refer to the specific version number.

Building
--------

I did not use the existing feature flag infra to configure the
experimental builds. The reason is because feature flags are designed
to configure a single package. They're not designed to generate multiple
forks of the same package; for each set of feature flags, you must
create a separate package configuration.

Instead, I've added a new build dimension called the **release
channel**. By default, builds use the **stable** channel. There's
also an **experimental** release channel. We have the option to add more
in the future.

There are now two dimensions per artifact: build type (production,
development, or profiling), and release channel (stable or
experimental). These are separate dimensions because they are
combinatorial: there are stable and experimental production builds,
stable and experimental developmenet builds, and so on.

You can add something to an experimental build by gating on
`__EXPERIMENTAL__`, similar to how we use `__DEV__`. Anything inside
these branches will be excluded from the stable builds.
This gives us a low effort way to add experimental behavior in any
package without setting up feature flags or configuring a new package.
2019-10-14 10:46:42 -07:00
Sebastian Markbåge
d5b54d0c35 [SuspenseList] Fix bugs with dropped Promises (#17082)
* Transfer any pending promises from inner boundary to list

For non-hidden modes, this boundary should commit so this shouldn't be
needed but the nested boundary can make a second pass which forces these
to be recreated without resuspending. In this case, the outer list assumes
that it can collect the inner promises to still rerender if needed.

* Propagate suspense "context" change to nested SuspenseLists

This means that we always rerender any nested SuspenseLists together.

This bug looks similar to the previous one but is not based on the lack of
retry but that the retry only happens on the outer boundary but the inner
doesn't get a retry ping since it didn't know about its own promise after
the second pass.
2019-10-14 09:42:10 -07:00
Andrew Clark
75955bf1d7 Pass prod error messages directly to constructor (#17063)
* Remove "Invariant Violation" from dev errors

When I made the change to compile `invariant` to throw expressions, I
left a small runtime to set the error's `name` property to "Invariant
Violation" to maintain the existing behavior.

I think we can remove it. The argument for keeping it is to preserve
continuity in error logs, but this only affects development errors,
anyway: production error messages are replaced with error codes.

* Pass prod error messages directly to constructor

Updates the `invariant` transform to pass an error message string
directly to the Error constructor, instead of mutating the
message property.

Turns this code:

```js
invariant(condition, 'A %s message that contains %s', adj, noun);
```

into this:

```js
if (!condition) {
  throw Error(
    __DEV__
      ? `A ${adj} message that contains ${noun}`
      : formatProdErrorMessage(ERR_CODE, adj, noun)
  );
}
```
2019-10-11 09:10:40 -07:00
Dominic Gannaway
0ac8e563d0 [react-interactions] Add getInstanceFromNode support to TestHostRenderer (#17065)
Fix bad WeakMap key case

Fix bad WeakMap key case
2019-10-11 16:58:27 +02:00
Brian Vaughn
22b2642a56 DevTools test shell tweaks (#17054)
* Updated DevTools shell ignore warning message to account for recent changes in warning text

* Update DevTools console patching to patch the parent window's console rather than the iframe, to more accurately simulate real usage environment
2019-10-09 12:37:25 -07:00
Eli White
4be45be5ff Stop warning about setNativeProps being deprecated (#17045)
* Stop warning about setNativeProps being deprecated

* Remove ReactNative.setNativeProps

* Remove more Fabric tests
2019-10-08 11:21:20 -07:00
Dominic Gannaway
b71ab61c8f [react-interactions] Adds more experimental Scope API methods (#17042) 2019-10-08 19:32:53 +02:00
Andrew Clark
5a71cbe7a9 Remove unused export
Meant to do this in e4b21be but neglected to `git add` the changes.
2019-10-07 15:32:34 -07:00
Andrew Clark
71d012ecd0 Remove dormant createBatch experiment (#17035)
* Remove dormant createBatch experiment

In a hybrid React app with multiple roots, `createBatch` is used to
coordinate an update to a root with its imperative container.

We've pivoted away from multi-root, hybrid React apps for now to focus
on single root apps.

This PR removes the API from the codebase. It's possible we'll add back
some version of this feature in the future.

* Remove unused export
2019-10-07 14:15:15 -07:00
Andrew Clark
cd1b167ad4 [Scheduler Profiler] Use microsecond precision (#17010)
The `performance.now` returns a timestamp in milliseconds as a float.
The browser has the option to adjust the precision of the float, but
it's usually more precise than a millisecond. However, this precision
is lost when the timestamp is logged by the Scheduler profiler, because
we store the numbers in an Int32Array.

This change multiplies the millisecond float value by 1000, giving us
three more degrees of precision.
2019-10-07 09:16:18 -07:00
Dominic Gannaway
55731fd8ce [react-interactions] Refine a11y component flow types (#17032) 2019-10-07 16:36:16 +02:00
Dominic Gannaway
a011aacafa [react-interactions] Remove FB builds of a11y components (#17030) 2019-10-07 12:45:49 +02:00
Dominic Gannaway
fff5b1ca77 [react-interactions] Add FocusTable colSpan support (#17019) 2019-10-07 12:04:41 +02:00
Luna Ruan
4bc52ef0df Revert "update hideOrUnhideAllChildren to hide portals that aren't wrapped in a host component (#16992)" (#17011)
This reverts commit de2edc268d.
2019-10-03 17:22:22 -07:00
Sebastian Markbåge
3a2b5f148d [Selective Hydration] ReactDOM.unstable_scheduleHydration(domNode) (#17004)
Adds an API to explicitly prioritize hydrating the path to a particular DOM node without relying on events to do it.

The API uses the current scheduler priority to schedule it. For the same priority, the last one wins. This allows a similar effect as continuous events. This is useful for example to hydrate based on scroll position, or prioritize components that will upgrade to client-rendered-only content.

I considered having an API that explicitly overrides the current target(s). However that makes it difficult to coordinate across components in an app.

This just hydrates one target at a time but if it is blocked on I/O we could consider increasing priority of later targets too.
2019-10-03 14:48:28 -07:00
Dominic Gannaway
26ba38ae4b [EnterLeaveEventPlugin] Fix bug when dealing with unhandled DOM nodes (#17006) 2019-10-03 23:35:09 +02:00
Andrew Clark
abedf17597 Changelog for v16.10.2 2019-10-03 14:16:13 -07:00
Andrew Clark
d256f88ac6 Update local version numbers for 16.10.2 release 2019-10-03 14:14:10 -07:00
Brian Vaughn
a8b8ffb894 DevTools v4.1.3 -> v4.2.0 2019-10-03 12:34:35 -07:00
Brian Vaughn
0545f366d4 Added trace updates feature (DOM only) (#16989)
* Added trace updates feature (DOM only)
* Updated DevTools CHANGELOG
2019-10-03 11:07:18 -07:00
Simen Bekkhus
e09097a75d chore: upgrade to jest 24 (#15778)
* chore: upgrade to jest 24

* download react-is from npm manually
2019-10-03 22:44:18 +05:30
Rane Wallin
5943b1da6c Fixing grammatical errors in error message (#16973)
* Fixing grammatical errors in error message

* Fixing grammar error in test file
2019-10-03 18:14:48 +05:30
Dominic Gannaway
4c5698400f [react-interactions] Remove context.setTimeout & context.clearTimeout (#17000) 2019-10-03 13:37:37 +02:00
Dominic Gannaway
b33633d932 [react-interactions] Repurpose React a11y modules (#16997) 2019-10-03 11:19:24 +02:00
Luna Ruan
de2edc268d update hideOrUnhideAllChildren to hide portals that aren't wrapped in a host component (#16992)
Currently, when a node suspends, if its subtree contains a portal, the portal is not hidden. This hides portals in the subtree when it's not wrapped in a host component .
2019-10-02 15:30:55 -07:00
Sebastian Markbåge
bb680a0905 [Selective Hydration] Prioritize the last continuous target (#16937)
* Prioritize the last continuous target

This ensures that the current focus target is always hydrated first.

Slightly higher than the usual Never expiration time used for hydration.
The priority increases with each new queued item so that the last always
wins.

* Don't export the moving target

It's not useful for comparison purposes anyway.
2019-10-02 14:52:23 -07:00
Eli White
10277cc5ba Remove unused canonical check in fiber host component (#16914) 2019-10-02 11:07:20 -07:00
Nicolas Gallagher
ab1a4f249e Move eventSystemFlags to last argument in event plugin extractors (#16978)
Fix for necolas/react-native-web#1443
2019-10-02 10:31:15 -07:00
Nicolas Gallagher
f6efb224b0 [react-interactions] Tap cancels on second pointerdown (#16936)
This patch causes onTapCancel to be called whenever a second pointer interacts
with the responder target.
2019-10-01 15:13:31 -07:00
Dominic Gannaway
34457729a6 [react-interactions] Add allowModifiers flag to FocusList + FocusTable (#16971) 2019-10-01 17:59:52 +02:00
Rango Yuan
b34f042e5b Fix mouseenter handlers fired twice (#16928) 2019-10-01 14:03:14 +02:00
Andrew Clark
05dc814cf0 Remove IIFE wrappers from dev invariant checks (#16963)
The error transform works by replacing calls to `invariant` with
an `if` statement.

Since we're replacing a call expression with a statement, Babel wraps
the new statement in an immediately-invoked function expression (IIFE).
This wrapper is unnecessary in practice because our `invariant` calls
are always part of their own expression statement.

In the production bundle, the function wrappers are removed by Closure.
But they remain in the development bundles.

This commit updates the transform to confirm that an `invariant` call
expression's parent node is an expression statement. (If not, it throws
a transform error.)

Then, it replaces the expression statement instead of the expression
itself, effectively removing the extraneous IIFE wrapper.
2019-09-30 11:14:51 -07:00
Brian Vaughn
2c8832075b React DevTools v4.1.2 -> v.4.1.3 2019-09-30 09:33:23 -07:00
Brian Vaughn
6c73a1e776 Updated DevTools CHANGELOG 2019-09-30 08:31:47 -07:00
David Huang
6a3de7a414 [DevTools] postMessage target origin needs to be '*' for local files (#16953) 2019-09-30 08:29:18 -07:00
Dominic Gannaway
ac8e8b3278 [react-interactions] Add tab handling to FocusList (#16958) 2019-09-30 17:13:35 +02:00
Dominic Gannaway
10c7dfe3b4 [react-interactins] FocusTable tabScope handling+tabIndex control (#16922) 2019-09-30 11:41:20 +02:00
Kirankumar Ambati
d3622d0f97 chore: updated comment message (#16949) 2019-09-29 15:00:49 -07:00
Andrew Clark
2a264a9dbe Update local version numbers for 16.10.1 release 2019-09-28 21:41:42 -07:00
Andrew Clark
22019ef5a2 Changelog for v16.10.1 2019-09-28 11:24:19 -07:00
Sebastian Markbåge
d8a76ad580 Allow Suspense Mismatch on the Client to Silently Proceed (#16943)
* Regression test: Suspense + hydration + legacy

* Allow Suspense Mismatch on the Client to Silently Proceed

This fixes but isn't actually the semantics that we want this case to have.
2019-09-28 10:43:53 -07:00
Sebastian Markbåge
9d637844e9 Remove enableUserBlockingEvents flag (#16882)
Seems like this worked out. We can clean up the flag now.
2019-09-27 19:46:56 -07:00
Sebastian Markbåge
fe31cc710e [Selective Hydration] Increase priority for non-synchronous discrete events and retries (#16935)
* Increase retryTime for increased priority dehydrated boundaries

* Increaese the priority to user blocking for every next discrete boundary
2019-09-27 17:27:17 -07:00
Brian Vaughn
b550679617 Fixed typo in DevTools CHANGELOG 2019-09-27 17:10:27 -07:00
Brian Vaughn
5184346daf DevTools v4.1.1 -> v4.1.2 2019-09-27 17:03:17 -07:00
Brian Vaughn
d4278663c6 Replaced === check with Object.is() to support values like NaN (#16934) 2019-09-27 16:54:53 -07:00
Nicolas Gallagher
d1121c0174 [react-interactions] Fix virtual click heuristic (#16915) 2019-09-27 15:38:47 -07:00
Andrew Clark
f553515d1e Fix heading level in changelog 2019-09-27 13:37:36 -07:00
Andrew Clark
7dc83a6100 Changelog for 16.10 2019-09-27 13:31:47 -07:00
Andrew Clark
93f5f11b79 Update local version numbers for 16.10 release 2019-09-27 13:31:35 -07:00
Luna Ruan
c8dc7a926e expose isHydrating (#16909)
expose isHydrating for FB
2019-09-26 14:47:01 -07:00
Eli White
db8afe4f63 Add HostComponent type to ReactNative (#16898)
* Add HostComponent type to ReactNative

* Use type alias imports instead of wildcard

* Fix forgotten Object in measureLayout type
2019-09-26 14:42:18 -07:00
Andrew Clark
fad5102101 [bugfix] Fix false positive render phase update (#16907)
Need to reset the current "debug phase" inside the catch block.
Otherwise React thinks we're still in the render phase during the
subsequent event.
2019-09-26 12:47:48 -07:00
Brian Vaughn
a9cd9a765b DevTools v4.1.0 -> v4.1.1 2019-09-26 10:22:59 -07:00
Brian Vaughn
b6606ecba8 DevTools shows unsupported renderer version dialog (#16897)
* DevTools shows unsupported renderer version dialog

* Optimistic CHANGELOG udpate
2019-09-26 08:41:46 -07:00
Brian Vaughn
84e83db1ee Updated DevTools CHANGELOG 2019-09-26 08:26:18 -07:00
Dominic Gannaway
b9811ed5bc [react-interactions] Add wrapping support to FocusList/FocusTable (#16903) 2019-09-26 15:15:48 +02:00
David Huang
49b0cb6db8 Moving backend injection to the content script (#16900) 2019-09-26 14:03:07 +01:00
Sebastian Markbåge
3694a3b5e9 Selective Hydration (#16880)
* Add Feature Flag for Selective Hydration

* Enable Synchronous Hydration of Discrete Events

* Resolve cyclic dependency
2019-09-25 15:26:27 -07:00
Dominic Gannaway
4bb0e96b4b [react-interactions] FocusTable key press bound propgataion (#16895) 2019-09-25 21:12:39 +02:00
Brian Vaughn
fa1a326227 Update useEditableValue hook to sync external value changes (#16878)
* Update useEditableValue to mirror value cahnges

Previously, the hook initialized local state (in useState) to mirror the prop/state value. Updates to the value were ignored though. (Once the state was initialized, it was never updated.) The new hook updates the local/editable state to mirror the external value unless there are already pending, local edits being made.

* Optimistic CHANGELOG update

* Added additional useEditableValue() unit test cases
2019-09-25 10:46:27 -07:00
Dominic Gannaway
57bf275fbd [devtools] Add support for React Scope symbol/number (#16893) 2019-09-25 19:03:37 +02:00
Dominic Gannaway
7c3bd08b37 [react-interactions] Add more documentation for a11y components (#16894) 2019-09-25 19:01:15 +02:00
Sebastian Markbåge
a06d181af0 Include tag in begin/complete invariant (#16881) 2019-09-25 08:10:35 -07:00
Sebastian Markbåge
0d8c0cd096 These flags are hard coded in our internal config (#16883)
By hard coding them here they can get properly DCE and don't have to be
sent to users. The internal config should only have dynamic flags.
2019-09-25 08:00:29 -07:00
Dominic Gannaway
d6d83d7060 [react-interactions] Add Portal propagation configuration (#16889) 2019-09-25 16:56:51 +02:00
Dominic Gannaway
d0ebde77f6 [react-interactions] Add initial docs explaining React Scopes (#16892) 2019-09-25 14:57:47 +02:00
Joshua Gross
32e5c97d11 [React Native] Improve errors for invalid ViewConfig getter functions (#16879)
* [React Native] Improve logging for missing view configs and invalid view config getter functions

* [React Native] Improve logging for missing view configs and invalid view config getter functions
2019-09-24 17:46:21 -07:00
Dominic Gannaway
ebc299fc2f [react-interactions] TabFocus -> FocusManager (#16874) 2019-09-24 23:26:20 +02:00
Dominic Gannaway
793f176dad [react-interactions] Make FocusList bundle (#16876) 2019-09-24 18:02:13 +02:00
Dominic Gannaway
68a87eee54 [react-interactions] Add FocusList component (#16875) 2019-09-24 17:14:29 +02:00
Jessica Franco
18d2e0c03e Warning system refactoring (part 1) (#16799)
* Rename lowPriorityWarning to lowPriorityWarningWithoutStack

This maintains parity with the other warning-like functions.

* Duplicate the toWarnDev tests to test toLowPriorityWarnDev

* Make a lowPriorityWarning version of warning.js

* Extract both variants in print-warning

Avoids parsing lowPriorityWarning.js itself as the way it forwards the
call to lowPriorityWarningWithoutStack is not analyzable.
2019-09-24 13:45:38 +01:00
Andrew Clark
8b580a89d6 Idle updates should not be blocked by hidden work (#16871)
* Idle updates should not be blocked by hidden work

Use the special `Idle` expiration time for updates that are triggered at
Scheduler's `IdlePriority`, instead of `Never`.

The key difference between Idle and Never¹ is that Never work can be
committed in an inconsistent state without tearing the UI. The main
example is offscreen content, like a hidden subtree.

¹ "Never" isn't the best name. I originally called it that because it
"never" expires, but neither does Idle. Since it's mostly used for
offscreen subtrees, we could call it "Offscreen." However, it's also
used for dehydrated Suspense boundaries, which are inconsistent in the
sense that they haven't finished yet, but aren't visibly inconsistent
because the server rendered HTML matches what the hydrated tree would
look like.

* Reset as early as possible using local variable

* Updates in a hidden effect should be Idle

I had made them Never to avoid an extra render when a hidden effect
updates the hidden component -- if they are Idle, we have to render once
at Idle, which bails out on the hidden subtree, then again at Never to
actually process the update -- but the problem of needing an extra
render pass to bail out hidden updates already exists and we should fix
that properly instead of adding yet another special case.
2019-09-23 20:52:48 -07:00
Nicolas Gallagher
c5e7190ed4 [react-interactions] Press with useRef instead of useState (#16870)
We only need to read and modify the value for the lifetime of the hook
2019-09-23 16:25:13 -07:00
Brian Vaughn
911104a129 DevTools CHANGELOG update 2019-09-23 12:58:58 -07:00
Brian Vaughn
bce2ac63a9 Revert change to backend injection method from PR #16752 (#16864)
PR #16752 changed how we were injecting the backend script to be done by the content script in order to work around Trusted Type limitations with our previous approach. This may have caused a regression (see #16840) so I'm backing it out to verify.
2019-09-23 12:56:36 -07:00
Brian Vaughn
9b3cde9b62 Fix DevTools v4.1 editable hook regression (#16867)
* Fixed a regression in hooks editor from a recent EditableValue change

* Fixed a reset/state bug in useEditableValue() hook and removed unnecessary useMemo()
2019-09-23 12:56:01 -07:00
Dominic Gannaway
1a6294d3e2 [react-interaction] Refactor a11y components more (#16866) 2019-09-23 21:30:49 +02:00
Dominic Gannaway
1758b3f7ba [react-interactions] Add no-op stopPropagation + preventDefault to Press (#16868)
Fix
2019-09-23 21:18:40 +02:00
Andrew Clark
013b7ad117 [suspense][error handling] Inline renderRoot and fix error handling bug (#16801)
* Outline push/pop logic in `renderRoot`

I want to get rid of the the `isSync` argument to `renderRoot`, and
instead use separate functions for concurrent and synchronous render.

As a first step, this extracts the push/pop logic that happens before
and after the render phase into helper functions.

* Extract `catch` block into helper function

Similar to previous commit. Extract error handling logic into
a separate function so it can be reused.

* Fork `renderRoot` for sync and concurrent

Removes `isSync` argument in favor of separate functions.

* Extra "root completion" logic to separate function

Moving this out to avoid an accidental early return, which would
bypass the call to `ensureRootIsScheduled` and freeze the UI.

* Inline `renderRoot`

Inlines `renderRoot` into `performConcurrentWorkOnRoot` and
`performSyncWorkOnRoot`. This lets me remove the `isSync` argument
and also get rid of a redundant try-catch wrapper.

* [suspense][error handling] Add failing unit test

Covers an edge case where an error is thrown inside the complete phase
of a component that is in the return path of a component that suspends.
The second error should also be handled (i.e. able to be captured by
an error boundary.

The test is currently failing because there's a call to
`completeUnitOfWork` inside the main render phase `catch` block. That
call is not itself wrapped in try-catch, so anything that throws is
treated as a fatal/unhandled error.

I believe this bug is only observable if something in the host config
throws; and, only in legacy mode, because in concurrent/batched mode,
`completeUnitOfWork` on fiber that throws follows the "unwind" path
only, not the "complete" path, and the "unwind" path does not call
any host config methods.

* [scheduler][profiler] Start time of delayed tasks

Fixes a bug in the Scheduler profiler where the start time of a delayed
tasks is always 0.

* Remove ad hoc `throw`

Fatal errors (errors that are not captured by an error boundary) are
currently rethrown from directly inside the render phase's `catch`
block. This is a refactor hazard because the code in this branch has
to mirror the code that happens at the end of the function, when exiting
the render phase in the normal case.

This commit moves the throw to the end, using a new root exit status.

* Handle errors that occur on unwind
2019-09-23 11:23:28 -07:00
Sebastian Markbåge
0a527707cd Event Replaying (#16725)
* Add Event Replaying Infra

* Wire up Roots and Suspense boundaries, to retry events, after they commit

* Replay discrete events in order in a separate scheduler callback

* Add continuous events

These events only replay their last target if the target is not yet
hydrated. That way we don't have to wait for a previously hovered
boundary before invoking the current target.

* Enable tests from before

These tests were written with replaying in mind and now we can properly
enable them.

* Unify replaying and dispatching

* Mark system flags as a replay and pass to legacy events

That way we can check if this is a replay and therefore needs a special
case. One such special case is "mouseover" where we check the
relatedTarget.

* Eagerly listen to all replayable events

To minimize breakages in a minor, I only do this for the new root APIs
since replaying only matters there anyway. Only if hydrating.

For Flare, I have to attach all active listeners since the current
system has one DOM listener for each. In a follow up I plan on optimizing
that by only attaching one if there's at least one active listener
which would allow us to start with only passive and then upgrade.

* Desperate attempt to save bytese

* Add test for mouseover replaying

We need to check if the "relatedTarget" is mounted due to how the old
event system dispatches from the "out" event.

* Fix for nested boundaries and suspense in root container

This is a follow up to #16673 which didn't have a test because it wasn't
observable yet. This shows that it had a bug.

* Rename RESPONDER_EVENT_SYSTEM to PLUGIN_EVENT_SYSTEM
2019-09-23 11:21:10 -07:00
Andrew Clark
a87d245fc2 [work loop] Prevent work loop from being inlined (#16865)
Uses Closure Compiler's `@noinline` directive.

See https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#noinline
2019-09-23 11:12:47 -07:00
Nicolas Gallagher
312b462d54 [react-interactions] Improve consistency of Tap responder (#16837)
Makes sure that touch events with modifier keys behave the same way as other
pointer types (i.e., does not call `onTapStart` if the gesture begins with a
modifier key held down)
2019-09-23 10:48:11 -07:00
Dominic Gannaway
70754f10d4 [react-interaction] Tweak Focus Table component (#16862) 2019-09-23 16:39:43 +02:00
Dominic Gannaway
d7f6dd5a80 [react-interactions] Fix typo in FocusTable (#16860) 2019-09-23 14:20:43 +02:00
Dan Abramov
cef47cbc01 Rename experimental react-ui => react-interactions (#16842) 2019-09-20 11:51:03 +01:00
Dominic Gannaway
57a5805a9f [react-ui] Add preventDefault+stopPropagation to Keyboard + update Focus components (#16833) 2019-09-20 11:21:38 +02:00
Brian Vaughn
08b51aa384 Added React DevTools v4.1.0 release date to CHANGELOG 2019-09-19 15:22:22 -07:00
Brian Vaughn
b5cebedfbe React DevTools version bump 4.0.6 -> 4.1.0 2019-09-19 15:11:48 -07:00
Sebastian Markbåge
35bf9d27a3 Exclude react-dom when flow checking other builds (#16737)
This is because the HostConfig can't be guaranteed to be consistent with
other code such as code that touches the DOM directly.

Ideally we'd have a more systemic solution to this since it will pop
up for other packages later too.
2019-09-19 12:41:51 -07:00
Nicolas Gallagher
fd870e6b6a [react-ui/events] Tap responder API changes (#16827)
This patch limits the `onTap*` callbacks to the primary pointer button.
Auxiliary button and modified primary button interactions call
`onAuxiliaryTap`, cancel any active tap, and preserve the native behavior.
2019-09-19 09:36:29 -07:00
Dan Abramov
4ddcb8e134 [DevTools] Remove Welcome dialog (#16834) 2019-09-19 08:41:18 -07:00
Dominic Gannaway
924a305780 [react-ui] Remove event object warnings (#16822) 2019-09-19 12:46:17 +02:00
halvves
a5df18a9e5 prevent firefox marking required textareas invalid (#16578)
* prevent firefox marking required textareas invalid

Bug was caused by an IE10/IE11 bugfix dealing with the placeholder attribute and textContent. Solved by avoiding the IE bugfix when textContent was empty.

Closes #16402

* more explicit conditional check for textContent

re: @philipp-spiess code review

* clarify textarea test fixture's expected result

better describe the behavior we are testing for
re: @philipp-spiess code review
2019-09-18 14:38:02 -07:00
Dan Abramov
f818af9b03 [Fresh] Always remount classes (#16823) 2019-09-18 16:32:11 +01:00
Ricky
6ecfa90eb0 [React Native] Fix for view config registrations (#16821) 2019-09-18 15:31:00 +01:00
Dominic Gannaway
18cb59050b [react-core] Do not null fiber.sibling in detachFiber (#16820) 2019-09-18 14:18:32 +02:00
Kuba Juszczyk
d862f0ea56 Optimize objectIs (#16212) 2019-09-17 23:55:43 +02:00
Pavlo Tymchuk
d1c2555861 [react-devtools-shared] Added string type check for object name prop in getDisplayName function (#16798)
* [react-devtools-shared] Added string type check for object name prop in getDisplayName function from utils.js file; tests included;

* Re-added empty string check to getDisplayName()

* Tweaked tests to use real functions

This more closely simulates how the utility is being used in production, and would catch cases like anonymous functions (with empty string names).
2019-09-17 13:17:04 -07:00
Brian Vaughn
70dcdd265d Updated pending CHANGELOG for DevTools 2019-09-17 13:15:53 -07:00
Brian Vaughn
e8c7ddeef2 Release script filters DevTools NPM pakcages (#16810) 2019-09-17 12:46:13 -07:00
Dominic Gannaway
8f1533f4d8 [react-ui] Fix bundle name [hotfix] (#16811) 2019-09-17 21:10:51 +02:00
Dominic Gannaway
7c802de797 [react-a11y] Add react-ui/accessibility to bundle build (#16804) 2019-09-17 20:22:09 +02:00
Andrew Clark
901139c291 [scheduler][profiler] Start time of delayed tasks (#16809)
Fixes a bug in the Scheduler profiler where the start time of a delayed
tasks is always 0.
2019-09-17 10:24:48 -07:00
Dominic Gannaway
f40ceb0010 [react-ui] FocusGrid -> ReactFocusTable + tweaks and fixes (#16806) 2019-09-17 19:22:10 +02:00
Dominic Gannaway
2f1e8c5f78 [react-core] Clear more properties in detachFiber (#16807) 2019-09-17 17:30:22 +02:00
Dan Abramov
8e0c574122 Follow-up to initial Trusted Types support (#16795)
* Follow-up to initial Trusted Types support

* Fast-path both strings and numbers

* Move shared objects out of every test
2019-09-17 16:06:26 +01:00
Nicolas Gallagher
3af05de1aa [react-ui] usePress from useKeyboard and useTap (#16772)
This implements 'usePress' in user-space as a combination of 'useKeyboard' and 'useTap'.  The existing 'usePress' API is preserved for now. The previous 'usePress' implementation is moved to 'PressLegacy'.
2019-09-16 14:36:27 -07:00
Dominic Gannaway
494300b366 [react-ui] Move experimental event+a11y work to react-ui package (#16794) 2019-09-16 20:05:50 +02:00
Nicolas Gallagher
9691eb273a [react-events] Keyboard support for virtual clicks (#16780)
This accounts for all clicks that are natively dispatched following relevant
keyboard interactions (e.g., key is "Enter"), as well as programmatic clicks,
and screen-reader virtual clicks.
2019-09-16 10:40:05 -07:00
Emanuel Tesař
b8d079b413 Add trusted types to react on client side (#16157)
* Add trusted types to react on client side

* Implement changes according to review

* Remove support for trusted URLs, change TrustedTypes to trustedTypes

* Add support for deprecated trusted URLs

* Apply PR suggesstions

* Warn only once, remove forgotten check, put it behind a flag

* Move comment

* Fix PR comments

* Fix html toString concatenation

* Fix forgotten else branch

* Fix PR comments
2019-09-16 13:43:22 +01:00
Heaven
cdbfa5044b fix typo inteval -> interval & continutation -> continuation (#16760)
* fix typo alterate -> alternate

* fix typo interal -> interval & continutation -> continuation
2019-09-14 12:51:20 -07:00
Andrew Clark
45b6443c90 Spelling is fundamental (#16782) 2019-09-13 16:27:18 -07:00
Andrew Clark
45898d0be0 [Scheduler] Prevent event log from growing unbounded (#16781)
If a Scheduler profile runs without stopping, the event log will grow
unbounded. Eventually it will run out of memory and the VM will throw
an error.

To prevent this from happening, let's automatically stop the profiler
once the log exceeds a certain limit. We'll also print a warning with
advice to call `stopLoggingProfilingEvents` explicitly.
2019-09-13 15:50:25 -07:00
Nicolas Gallagher
87eaa90ef8 [react-events] Keyboard calls preventDefault on 'click' events (#16779)
Make sure to call preventDefault for any 'click' events that follow a 'keydown'
event that matches 'preventKeys'
2019-09-13 13:19:18 -07:00
Brian Vaughn
0c0b30b8c7 Remove unnecessary interaction tracing ping wrapper (#16777) 2019-09-13 11:04:36 -07:00
Andrew Clark
137ea783b1 Re-enable risky work loop changes (#16771)
The stack of PRs in #16743 was reverted. This adds them back.
2019-09-13 09:33:46 -07:00
Brian Vaughn
d6f6b951e1 Support disabling interaction tracing for suspense promises (#16776)
* Support disabling interaction tracing for suspense promises

If a thrown Promise has the __reactDoNotTraceInteractions attribute, React will not wrapped its callbacks to continue tracing any current interaction(s).

* Added optional '__reactDoNotTraceInteractions' attribute to Flow Thenable type
2019-09-13 08:59:57 -07:00
Dominic Gannaway
b4b8a349a3 [react-interactions] Add experimental FocusGrid API (#16766) 2019-09-13 12:29:39 +02:00
Andrew Clark
a7dabcb60a Revert "Re-arrange slightly to prevent refactor hazard (#16743)" (#16769)
This reverts commit ab4951fc03.

* Track "pending" and "suspended" ranges

A FiberRoot can have pending work at many distinct priorities. (Note: we
refer to these levels as "expiration times" to distinguish the concept
from Scheduler's notion of priority levels, which represent broad
categories of work. React expiration times are more granualar. They're
more like a concurrent thread ID, which also happens to correspond to a
moment on a timeline. It's an overloaded concept and I'm handwaving over
some of the details.)

Given a root, there's no convenient way to read all the pending levels
in the entire tree, i.e. there's no single queue-like structure that
tracks all the levels, because that granularity of information is not
needed by our algorithms. Instead we track the subset of information
that we actually need — most importantly, the highest priority level
that exists in the entire tree.

Aside from that, the other information we track includes the range of
pending levels that are known to be suspended, and therefore should not
be worked on.

This is a refactor of how that information is tracked, and what each
field represents:

- A *pending* level is work that is unfinished, or not yet committed.
  This includes work that is suspended from committing.
  `firstPendingTime` and `lastPendingTime` represent the range of
  pending work. (Previously, "pending" was the same as "not suspended.")
- A *suspended* level is work that did not complete because data was
  missing. `firstSuspendedTime` and `lastSuspendedTime` represent the
  range of suspended work. It is a subset of the pending range. (These
  fields are new to this commit.)
- `nextAfterSuspendedTime` represents the next known level that comes
  after the suspended range.

This commit doesn't change much in terms of observable behavior. The one
change is that, when a level is suspended, React will continue working
on the next known level instead of jumping straight to the last pending
level. Subsequent commits will use this new structure for a more
substantial refactor for how tasks are scheduled per root.

* Get next expiration time from FiberRoot

Given a FiberRoot, we should be able to determine the next expiration
time that needs to be worked on, taking into account the levels that
are pending, suspended, pinged, and so on.

This removes the `expirationTime` argument from
`scheduleCallbackForRoot`, and renames it to `ensureRootIsScheduled` to
reflect the new signature. The expiration time is instead read from the
root using a new function, `getNextExpirationTimeToWorkOn`.

The next step will be to remove the `expirationTime` argument from
`renderRoot`, too.

* Don't bind expiration time to render callback

This is a fragile pattern because there's only meant to be a single
task per root, running at a single expiration time. Instead of binding
the expiration time to the render task, or closing over it, we should
determine the correct expiration time to work on using fields we
store on the root object itself.

This removes the "return a continuation" pattern from the
`renderRoot` function. Continuation handling is now handled by
the wrapper function, which I've renamed from `runRootCallback` to
`performWorkOnRoot`. That function is merely an entry point to
`renderRoot`, so I've also removed the callback argument.

So to sum up, at at the beginning of each task, `performWorkOnRoot`
determines which expiration time to work on, then calls `renderRoot`.
And before exiting, it checks if it needs to schedule another task.

* Update error recovery test to match new semantics

* Remove `lastPendingTime` field

It's no longer used anywhere

* Restart on update to already suspended root

If the work-in-progress root already suspended with a delay, then the
current render definitely won't finish. We should interrupt the render
and switch to the incoming update.

* Restart on suspend if return path has an update

Similar to the previous commit, if we suspend with a delay, and
something in the return path has a pending update, we should abort
the current render and switch to the update instead.

* Track the next unprocessed level globally

Instead of backtracking the return path. The main advantage over the
backtracking approach is that we don't have to backtrack from the source
fiber. (The main disadvantages are that it requires another module-level
variable, and that it could include updates from unrelated
sibling paths.)

* Re-arrange slightly to prevent refactor hazard

It should not be possible to perform any work on a root without
calling `ensureRootIsScheduled` before exiting. Otherwise, we could
fail to schedule a callback for pending work and the app could freeze.

To help prevent a future refactor from introducing such a bug, this
change makes it so that `renderRoot` is always wrapped in try-finally,
and the `finally` block calls `ensureRootIsScheduled`.

* Remove recursive calls to `renderRoot`.

There are a few leftover cases where `renderRoot` is called recursively.
All of them are related to synchronously flushing work before its
expiration time.

We can remove these calls by tracking the last expired level on the
root, similar to what we do for other types of pending work, like pings.

* Remove argument from performSyncWorkOnRoot

Read the expiration time from the root, like we do
in performConcurrentWorkOnRoot.
2019-09-12 14:21:57 -07:00
Dominic Gannaway
4b0b556dcf [react-interactions] Refactor TabFocusController (#16768) 2019-09-12 22:28:07 +02:00
Brian Vaughn
fb39f62925 Added upcoming changes to DevTools CHANGELOG 2019-09-12 08:34:28 -07:00
Anton Korzunov
ba932a5ad9 fix: inspect ClassComponent.render instead of constructor, fixes #16749 (#16759) 2019-09-12 08:32:42 -07:00
Dominic Gannaway
35a202d0e7 [react-events] Ensure we restore currentInstance + currentTimers (#16758) 2019-09-12 12:44:05 +02:00
Dominic Gannaway
3717c25a7e [react-interactions] More Tab Focus control handling (#16751) 2019-09-11 22:35:33 +02:00
Andrew Clark
0a2215cc0e [Scheduler][www] Put profiling feature behind flag (#16757)
Our infra currently doesn't support loading a separate profiling
build of Scheduler. Until that's fixed, the recommendation is to load
a single build and gate the profiling feature behind a flag.

Alternative to #16659
2019-09-11 13:28:03 -07:00
Brian Vaughn
8f03109cd2 Moved backend injection to the content script (#16752)
* Moved backend injection logic to content script

* Moved backend injection logic to content script

* Moved injection logic to content script

* Formatting changes

* remove ability to inject arbitrary scripts

* Removed done(), added some comments explaining the change

* Lint fixes

* Moved inline comment.

* Deleted inject() script since it was no longer being used
2019-09-11 09:51:32 -07:00
Brian Vaughn
efa780d0ab Removed DT inject() script since it's no longer being used 2019-09-11 09:51:24 -07:00
Brian Vaughn
4290967d4c Merge branch 'tt-compat' of https://github.com/onionymous/react into onionymous-tt-compat 2019-09-11 09:34:31 -07:00
Brian Vaughn
f09854a9e8 Moved inline comment. 2019-09-11 09:30:57 -07:00
Stephanie Ding
776d1c69b9 Lint fixes 2019-09-11 08:11:14 -07:00
Dominic Gannaway
3a49dff386 [react-events] Use context.objectAssign in Tap responder (#16748) 2019-09-11 17:06:40 +02:00
Stephanie Ding
2e75000f40 Removed done(), added some comments explaining the change 2019-09-11 08:05:27 -07:00
Matt Kane
56114a4b22 Change trackedTouchCount console.error to warn (#16750) 2019-09-11 14:10:26 +02:00
Dominic Gannaway
ae724be7be [react-interactions] Add TabFocusContainer and TabbableScope UI components (#16732) 2019-09-11 12:46:41 +02:00
Andrew Clark
ab4951fc03 Re-arrange slightly to prevent refactor hazard (#16743)
* Track "pending" and "suspended" ranges

A FiberRoot can have pending work at many distinct priorities. (Note: we
refer to these levels as "expiration times" to distinguish the concept
from Scheduler's notion of priority levels, which represent broad
categories of work. React expiration times are more granualar. They're
more like a concurrent thread ID, which also happens to correspond to a
moment on a timeline. It's an overloaded concept and I'm handwaving over
some of the details.)

Given a root, there's no convenient way to read all the pending levels
in the entire tree, i.e. there's no single queue-like structure that
tracks all the levels, because that granularity of information is not
needed by our algorithms. Instead we track the subset of information
that we actually need — most importantly, the highest priority level
that exists in the entire tree.

Aside from that, the other information we track includes the range of
pending levels that are known to be suspended, and therefore should not
be worked on.

This is a refactor of how that information is tracked, and what each
field represents:

- A *pending* level is work that is unfinished, or not yet committed.
  This includes work that is suspended from committing.
  `firstPendingTime` and `lastPendingTime` represent the range of
  pending work. (Previously, "pending" was the same as "not suspended.")
- A *suspended* level is work that did not complete because data was
  missing. `firstSuspendedTime` and `lastSuspendedTime` represent the
  range of suspended work. It is a subset of the pending range. (These
  fields are new to this commit.)
- `nextAfterSuspendedTime` represents the next known level that comes
  after the suspended range.

This commit doesn't change much in terms of observable behavior. The one
change is that, when a level is suspended, React will continue working
on the next known level instead of jumping straight to the last pending
level. Subsequent commits will use this new structure for a more
substantial refactor for how tasks are scheduled per root.

* Get next expiration time from FiberRoot

Given a FiberRoot, we should be able to determine the next expiration
time that needs to be worked on, taking into account the levels that
are pending, suspended, pinged, and so on.

This removes the `expirationTime` argument from
`scheduleCallbackForRoot`, and renames it to `ensureRootIsScheduled` to
reflect the new signature. The expiration time is instead read from the
root using a new function, `getNextExpirationTimeToWorkOn`.

The next step will be to remove the `expirationTime` argument from
`renderRoot`, too.

* Don't bind expiration time to render callback

This is a fragile pattern because there's only meant to be a single
task per root, running at a single expiration time. Instead of binding
the expiration time to the render task, or closing over it, we should
determine the correct expiration time to work on using fields we
store on the root object itself.

This removes the "return a continuation" pattern from the
`renderRoot` function. Continuation handling is now handled by
the wrapper function, which I've renamed from `runRootCallback` to
`performWorkOnRoot`. That function is merely an entry point to
`renderRoot`, so I've also removed the callback argument.

So to sum up, at at the beginning of each task, `performWorkOnRoot`
determines which expiration time to work on, then calls `renderRoot`.
And before exiting, it checks if it needs to schedule another task.

* Update error recovery test to match new semantics

* Remove `lastPendingTime` field

It's no longer used anywhere

* Restart on update to already suspended root

If the work-in-progress root already suspended with a delay, then the
current render definitely won't finish. We should interrupt the render
and switch to the incoming update.

* Restart on suspend if return path has an update

Similar to the previous commit, if we suspend with a delay, and
something in the return path has a pending update, we should abort
the current render and switch to the update instead.

* Track the next unprocessed level globally

Instead of backtracking the return path. The main advantage over the
backtracking approach is that we don't have to backtrack from the source
fiber. (The main disadvantages are that it requires another module-level
variable, and that it could include updates from unrelated
sibling paths.)

* Re-arrange slightly to prevent refactor hazard

It should not be possible to perform any work on a root without
calling `ensureRootIsScheduled` before exiting. Otherwise, we could
fail to schedule a callback for pending work and the app could freeze.

To help prevent a future refactor from introducing such a bug, this
change makes it so that `renderRoot` is always wrapped in try-finally,
and the `finally` block calls `ensureRootIsScheduled`.

* Remove recursive calls to `renderRoot`.

There are a few leftover cases where `renderRoot` is called recursively.
All of them are related to synchronously flushing work before its
expiration time.

We can remove these calls by tracking the last expired level on the
root, similar to what we do for other types of pending work, like pings.

* Remove argument from performSyncWorkOnRoot

Read the expiration time from the root, like we do
in performConcurrentWorkOnRoot.
2019-09-10 20:07:12 -07:00
Sebastian Markbåge
b0a8a3e041 Mark root as already hydrated after committing (#16739)
* Mark root as already hydrated after committing

* Remove current/child check for hydration and rely on the root flag instead
2019-09-10 20:02:02 -07:00
Sebastian Markbåge
e04f4259c4 Handle SuspenseListComponent getting retried (#16745)
This happens for example when a deleted boundary transfers its pending
promises to the list so that the list can be retried.

This wasn't caught by unit tests because this flag wasn't on in those
tests.
2019-09-10 19:38:44 -07:00
Stephanie Ding
8a6cd3cd12 remove ability to inject arbitrary scripts 2019-09-10 18:06:23 -07:00
Stephanie Ding
d51f062d03 Formatting changes 2019-09-10 17:46:29 -07:00
Stephanie Ding
85c7211014 Moved injection logic to content script 2019-09-10 17:45:27 -07:00
Stephanie Ding
788036c7ed Moved backend injection logic to content script 2019-09-10 17:34:12 -07:00
Stephanie Ding
c93038fabe Moved backend injection logic to content script 2019-09-10 17:22:04 -07:00
Brian Vaughn
2c98af77c3 DevTools: Props editing interface tweaks (#16740)
* Fix DevTools new prop input size
* Don't allow adding new values unless an overridePropsFn function has been provided.
* Do not show empty 'none' label ablve a new prop input
2019-09-10 14:57:33 -07:00
Brian Vaughn
2ce5801c25 Added upcoming changes to DevTools CHANGELOG 2019-09-10 13:32:53 -07:00
Hristo Kanchev
709baf1fec [DevTools] Support for adding props | Improved state/props value editing (#16700)
* Extracted sanitizeForParse

* Added canAddEntries flag to InspectedElementTree

* Added EditableKey component.

* Added support to add an additional entry.

* Added support to add more complex data structures in the EditableValue component. Added support to change the dataType of the value that is being changed.

* Fixed flow error.

* Removed unneeded fragment.

* Renamed EditableKey -> EditableName

* Removed unneeded dependency

* Removed problematic props to state hook.

* Prettified changes.

* Removed unused import.

* Fixed shouldStringify check.

* Removed testing props from EditableProps.

* Made some inline tweaks
2019-09-10 13:30:43 -07:00
Hristo Kanchev
4ef6387d6e [DevTools] [Context] Legacy Context (#16617)
* Added hasLegacyContext check.

* Passed hasLegacyContext as prop to SelectedElement

* Changing context labels based on hasLegacyContext

* Fixed flow types.

* Fixed typos.

* Added tests for hasLegacyContext.

* Renamed test.

* Removed test imports.
2019-09-10 13:30:20 -07:00
Liad Yosef
c317fc273b Correct link for troubleshooting react-dev-tools (#16690) (#16708)
* Correct link for troubleshooting react-dev-tools (#16690)

As pointed out in #16690 - the link for 'React Tab Doesn't Show Up' points to the empty README.MD.
This points it to that section in the v3 version README.MD - until an updated section will be added to the new dev-tools.

* Add a "The React Tab Doesn't Show Up" section

Add the troubleshooting section to the react dev tools readme

* point to the correct section in react-dev-tools readme

After adding the troubleshooting section to the readme - this will point to the correct place

* Moved README file to GitHub

* Update new issue link to include DevTools label
2019-09-10 13:14:19 -07:00
Nicolas Gallagher
41a78cd85c [react-events] Tap: add maximumDistance prop (#16689)
A prop for configuring the maximum distance that the active pointer can move before the tap is cancelled.
2019-09-10 12:52:43 -07:00
Dan Abramov
2400400788 react-refresh@0.4.2 2019-09-10 20:46:34 +01:00
Dan Abramov
ba6bb0fccf [Fresh] Hash signatures (#16738) 2019-09-10 20:28:13 +01:00
Dominic Gannaway
fd3e8cb0ae [react-events] Remove stopPropagation (Press) + use document for delegation (#16730) 2019-09-10 20:31:24 +02:00
Heaven
38c03ce006 Fix typo in commet (#16727) 2019-09-10 10:27:38 -07:00
Hristo Kanchev
4905590e1e Fixed font family issue in FF. (#16701) 2019-09-09 16:21:04 -07:00
Daniel Lo Nigro
35f447ddbf Remove console.log from copyWithSet (#16716) 2019-09-09 16:18:09 -07:00
Sebastian Markbåge
440cbf2ee5 Let's schedule the passive effects even earlier (#16714)
It turns out I needed to schedule mine in the mutation phase and there
are also clean up life-cycles there.
2019-09-09 15:06:03 -07:00
Sebastian Markbåge
cc2492ccf1 Schedule passive callbacks before layout effects are invoked (#16713) 2019-09-09 13:34:57 -07:00
Nicolas Gallagher
031eba789f [react-events] Tap: change order of events (#16694)
Before:

start -> change -> update -> end (cancel) -> change

Now:

start -> change -> update -> change -> end (cancel)
2019-09-09 09:08:17 -07:00
Nicolas Gallagher
f26fe8c0a7 [react-events] Keyboard: fix callback return types (#16693) 2019-09-09 09:07:42 -07:00
Heaven
9444c876d5 Remove wrong copy-paste code in test (#16695) 2019-09-09 11:34:08 +01:00
Dan Abramov
b260bef398 [Fresh] Add skipEnvCheck option to Babel plugin (#16688) 2019-09-06 20:30:16 +01:00
Dan Abramov
2f15881859 react-refresh@0.4.1 2019-09-06 20:02:43 +01:00
Dan Abramov
9044bb0fa3 [Fresh] Fix a crash with implicit arrow return (#16687) 2019-09-06 19:58:07 +01:00
Dan Abramov
21d79ce040 Add FreshRuntime WWW bundle, remove ESLint (#16684) 2019-09-06 16:48:07 +01:00
Alex Rohleder
206d61f722 fix typos on react-devtools comments (#16681) 2019-09-06 07:47:44 -07:00
Heaven
61836fba2a Fix typo: wnless -> unless (#16680) 2019-09-06 07:47:35 -07:00
Sebastian Markbåge
e11bf42cea Check for Suspense boundary in a root Container (#16673)
If we find a Container that might mean that we're on a node that is inside
a Suspense boundary that is directly inside the Container root.

Imagine the div is a Container and the span is a dehydrated instance:

```
<div>
  <!--$-->
  <span />
  <!--/$-->
</div>
```

There's no way to tests this yet since I'm not actually utilizing
the return value yet.

The solution is to just use the same path to check for a Suspense boundary
as if we find a parent instance.
2019-09-05 16:06:05 -07:00
Dan Abramov
962dfc2c33 Remove experimental scheduler flags (#16672) 2019-09-05 20:08:06 +01:00
Nicolas Gallagher
ff006451ad [react-events] Fix isTargetWithinNode type (#16671)
isTargetWithinNode passes the childTarget to getClosestInstanceFromNode which
does not account for a null value of 'node'.
2019-09-05 11:36:31 -07:00
Dan Abramov
040ca0fad7 Enable MessageLoop implementation by default (#16408) 2019-09-05 19:25:51 +01:00
Brian Vaughn
d96f478f8a use-subscription tearing fix (#16623)
* Add (failing) subscription tearing test and bugfix
* Added more inline comments to test
* Simplified tearing test case slightly
2019-09-05 11:12:46 -07:00
Luna Ruan
79e46b6778 updated flags from false to dicated on www (#16647) 2019-09-05 09:51:44 -07:00
Sebastian Markbåge
8d7c733f1f [Partial Hydration] Don't invoke listeners on parent of dehydrated event target (#16591)
* Don't invoke listeners on parent of dehydrated event target

* Move Suspense boundary check to getClosestInstanceFromNode

Now getClosestInstanceFromNode can return either a host component,
host text component or suspense component when the suspense
component is dehydrated.

We then use that to ignore events on a suspense component.

* Attach the HostRoot fiber to the DOM container

This lets us detect if an event happens on this root's subtree before it
has rendered something.

* Add todo

The approach of checking isFiberMounted answers if we might be in an
in-progress hydration but it doesn't answer which root or boundary
might be in-progress so we don't know what to wait for.

This needs some refactoring.

* Refactor isFiberMountedImpl to getNearestMountedFiber

We'll need the nearest boundary for event replaying so this prepares for
that.

This surfaced an issue that we attach Hydrating tag on the root but normally
this (and Placement) is attached on the child. This surfaced an issue
that this can lead to both Placement and Hydrating effects which is not
supported so we need to ensure that we only ever use one or the other.

* Add todo for bug I spotted

* Cache tags

* Check the ContainerInstanceKey before the InstanceKey

The container is inside the instance, so we must find it before the
instance, since otherwise we'll miss it.
2019-09-05 08:51:31 -07:00
Nicolas Gallagher
9ce8711d5a [react-events] Tap responder (#16628)
This is a partial replacement for the 'Press' responder:

1. `useTap` is scoped to pointers (no keyboard support). Our current thinking is
that "responders" should be limited to working with pointers, and that they can
be combined with 'useKeyboard' in user-space. For example, we might create a
'usePress' hook in user-space that combines 'useTap' with 'useKeyboard' to react
to both pointers and keyboard interactions.

2. `useTap` cancels the gesture once the pointer moves over an element that is
not within the responder target's subtree. This differs from `usePress` (and
React Native), where the gesture remains active after the pointer exits the
target's subtree and is restarted once the pointer reenters. One of the
drawbacks with the `usePress` behavior is that it requires repeatedly measuring
DOM elements (which can cause jank) to perform hit region tests. `useTap` avoids
doing this and relies on `document.elementFromPoint` only to support the
TouchEvent fallbacks.

3. `useTap` calls `onTapUpdate` when the active gesture's state changes,
`onTapEnd` when the gesture successfully completes. and `onTapCancel` when it
fails. There is no `onTap` callback. `usePress` did not explicitly report back
when the gesture failed, and product developers were confused about the
difference between `onPress` and `onPressEnd`.

4. `useTap` explicitly separates the PointerEvent implementation from the
MouseEvent/TouchEvent fallback.

5. `useTap` has better unit test coverage . All pointer types and the fallback
environment are tested. The shape of the gesture state object is also defined
and tested.
2019-09-04 17:09:33 -07:00
Dominic Gannaway
e86146e714 [react-events] Refine executeUserEventHandler (#16662) 2019-09-05 00:36:29 +01:00
Dominic Gannaway
c66edb9f8b [react-events] Refactor getCurrentTarget to getResponderNode (#16660) 2019-09-04 20:04:35 +01:00
Dominic Gannaway
9ff60ff16b [react-events] Fix Scope listener issue (#16658) 2019-09-04 18:57:39 +01:00
Dominic Gannaway
7126a37bf4 [react-events] Keyboard responder propagation handling (#16657) 2019-09-04 18:25:05 +01:00
Dominic Gannaway
539640d89f [react-events] Various core tweaks for event responder system (#16654) 2019-09-04 18:05:56 +01:00
Dominic Gannaway
af032764a9 [react-events] Adds preventKeys support to Keyboard responder (#16642) 2019-09-04 01:38:36 +01:00
Brian Vaughn
f705e2bac7 Updated pending CHANGELOG for DevTools 2019-09-03 08:37:12 -07:00
Hristo Kanchev
77bb102398 [DevTools] [Profiler]: Save profile now working in Firefox (#16612)
* Added anchor dom element in order to successfully download profiling data.
* Reworked downloadFile to accept a DOMElement in order for FF to successfully download profiling data.
* Prettify downloadFile changes.
2019-09-03 08:35:12 -07:00
Heaven
92f094d86d fix typo: oncurrent - concurrent (#16633) 2019-09-02 11:21:48 +01:00
Dominic Gannaway
46f912fd57 [react-core] Add more support for experimental React Scope API (#16621) 2019-08-30 18:27:14 +01:00
Paul O’Shannessy
2c1e6bf619 Adopt Contributor Covenant (#16613)
In order to foster healthy open source communities, we're adopting the
[Contributor Covenant](https://www.contributor-covenant.org/). It has been
built by open source community members and represents a shared understanding of
what is expected from a healthy community.
2019-08-29 16:04:47 -07:00
Brian Vaughn
f962feb882 Updated extensions build-from-source instructions in README 2019-08-29 08:49:08 -07:00
Simen Bekkhus
ac6193687f add integrity field in yarn.lock (#16601) 2019-08-29 16:36:02 +01:00
Sebastian Silbermann
16329bd954 chore: Update nvmrc with latest lts (#16610) 2019-08-29 16:30:35 +01:00
Dominic Gannaway
4e544cffee [react-events] Split out mixed event responder tests (#16608) 2019-08-29 16:13:37 +01:00
Gerald Monaco
f61138e068 Use renderToStaticMarkup for tests (#16516) 2019-08-29 16:08:38 +01:00
James George
980112b146 rephrase comment (#16559) 2019-08-29 14:51:07 +01:00
Bas Peeters
8a7c2e50f1 Remove duplicate character in regex group (#16572) 2019-08-29 14:49:27 +01:00
Tom Quirk
557d472fe3 add <thead>, <tfoot> to table > tr warning (#16535) 2019-08-29 14:46:27 +01:00
Simen Bekkhus
37fcd04681 chore: upgrade to danger 9 (#16602) 2019-08-29 13:46:53 +01:00
Dominic Gannaway
bd79be9b68 [react-core] Add experimental React Scope component API (#16587) 2019-08-29 12:06:51 +01:00
Brian Vaughn
996acf9036 Updated DevTools extension build script to work when run remotely (#16603) 2019-08-28 17:01:26 -07:00
Dominic Gannaway
34aaec6f90 [react-events] Ensure screen reader virtual clicks support preventDefault (#16600) 2019-08-28 17:39:07 +01:00
Dan Abramov
01fb68b9bf Don't ignore dependencies for render phase update (#16574) 2019-08-28 16:55:56 +01:00
LEE SUK JAE
1b585f630b Fix link on error-codes/README.md (#16595) 2019-08-28 15:49:45 +01:00
Brian Vaughn
0f3e82f3c4 Merge branch 'devtools-v4-merge' 2019-08-28 07:39:49 -07:00
Brian Vaughn
b8390310b1 Revert "Import React DevTools v4"
This reverts commit b438699d36.
2019-08-28 07:39:32 -07:00
Brian Vaughn
b438699d36 Import React DevTools v4
Imports the entire React DevTools v4 git repository (with history).
2019-08-28 07:35:53 -07:00
Brian Vaughn
ada5991422 Removed an unnecessary/unused DT Flow type 2019-08-28 07:28:06 -07:00
Brian Vaughn
08ce280cbc Updated DT regression fixture path 2019-08-28 07:25:52 -07:00
Brian Vaughn
b034ac6d38 Merge branch 'master' into devtools-v4-merge 2019-08-28 07:13:49 -07: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
Nicolas Gallagher
cb15f18dc1 [react-events] Improve mock event object accuracy (#16590)
* Better simulation for pointercancel
* Fix pressure values for different pointers
* Add describe/test helpers for pointer events
2019-08-27 15:45:54 -07:00
Brian Vaughn
bc8b15332b Updated README docs, example screenshots, etc 2019-08-27 15:20:34 -07:00
Brian Vaughn
7153dd516f Fixed a StyleEditor variable resolution regression 2019-08-27 12:53:38 -07:00
Brian Vaughn
33d439f8fd Merge branch 'master' into devtools-v4-merge 2019-08-27 11:00:41 -07:00
Brian Vaughn
fb316787cb Removed unused Chrome Flow types 2019-08-27 10:54:21 -07:00
Brian Vaughn
8e1434e80e Added FB copyright header 2019-08-27 10:54:01 -07:00
Brian Vaughn
49b0f87d10 Suppress act/renderer warning for DevTools tests 2019-08-27 10:46:27 -07:00
Brian Vaughn
8c684bf7e1 Removed forked DevTools Flow types 2019-08-27 10:42:02 -07:00
Brian Vaughn
9a016c0c2b Removed outdated snapshot 2019-08-27 10:31:36 -07:00
Brian Vaughn
f55b4f8e28 CI runs DevTools tests against built source 2019-08-27 10:28:58 -07:00
Dominic Gannaway
4ef269606c [react-events] Support screen reader virtual clicks (#16584) 2019-08-27 17:32:50 +01:00
Brian Vaughn
892ca8137e Disabled DevTools tests from yarn-build target 2019-08-27 09:08:49 -07:00
Brian Vaughn
896c993ada Fixed remaining DevTools broken tests by fixing a hydration/spread bug 2019-08-27 08:50:36 -07:00
Brian Vaughn
e3cc42be97 Fix Console patching test by resetting modules 2019-08-26 13:53:29 -07:00
Brian Vaughn
177f357d9d Updated DevTools test setup to no longer mock test renerer 2019-08-26 13:46:00 -07:00
Brian Vaughn
a48593a8d3 Iterating on DevTools tests: Trying to run tests against pre-build react-dom and react-test-renderers 2019-08-26 13:43:09 -07:00
Brian Vaughn
ee4806f47a Fixed flushing problem with tests 2019-08-26 13:08:35 -07:00
Brian Vaughn
9d4fd7a249 Merged changes from 4.0.5 -> 4.0.6 from DevTools fork 2019-08-26 10:12:18 -07:00
Brian Vaughn
4c1514495b Merge branch 'source' of github.com:bvaughn/react-devtools-experimental 2019-08-26 10:06:00 -07:00
Brian Vaughn
13a93e7b82 Configured CI to run DevTools tests. Updated other test configs not to include DevTools tests. 2019-08-26 09:58:28 -07:00
Brian Vaughn
c00a920640 Merge branch 'master' into devtools-v4-merge 2019-08-26 09:42:25 -07:00
Brian Vaughn
0da7bd0604 React DevTools CHANGELOG entry for 4.0.6 2019-08-26 09:34:06 -07:00
Brian Vaughn
a39d9c3dff 4.0.5 -> 4.0.6 2019-08-26 08:42:38 -07:00
Brian Vaughn
1e3b0b520e Added a null check around memoizedProps 2019-08-24 09:04:26 -07:00
Brian Vaughn
84b492f344 Polyfill Symbol usage 2019-08-23 17:38:45 -06:00
Dominic Gannaway
fc80772078 [react-events] Ensure updateEventListeners updates in commit phase (#16540) 2019-08-22 23:58:16 +01:00
Dan Abramov
0f6e3cd61c [Scheduler] Profiler Features (second try) (#16542)
* Revert "Revert "[Scheduler] Profiling features (#16145)" (#16392)"

This reverts commit 4ba1412305.

* Fix copy paste mistake

* Remove init path dependency on ArrayBuffer

* Add a regression test for cancelling multiple tasks

* Prevent deopt from adding isQueued later

* Remove pop() calls that were added for profiling

* Verify that Suspend/Unsuspend events match up in tests

This currently breaks tests.

* Treat Suspend and Resume as exiting and entering work loop

Their definitions used to be more fuzzy. For example, Suspend didn't always fire on exit, and sometimes fired when we did _not_ exit (such as at task enqueue).

I chatted to Boone, and he's saying treating Suspend and Resume as strictly exiting and entering the loop is fine for their use case.

* Revert "Prevent deopt from adding isQueued later"

This reverts commit 9c30b0b695d81e9c43b296ab93d895e4416ef713.

Unnecessary because GCC

* Start counter with 1

* Group exports into unstable_Profiling namespace

* No catch in PROD codepath

* No label TODO

* No null checks
2019-08-22 13:58:12 -07:00
Nicolas Gallagher
474b650cac [react-events] Rename hook exports (#16533)
For example, 'useHoverResponder' becomes 'useHover'
2019-08-22 13:30:35 -07:00
Nicolas Gallagher
2f03aa6eed [react-events] Fix middle-click for Press (#16546)
Browsers always report 'buttons' as 0 when a pointer is released.
2019-08-22 10:22:14 -07:00
Bruno Scopelliti
16c3408638 Only warn in case the fourth argument is a function (#16543) 2019-08-22 17:31:27 +01:00
Sebastian Markbåge
05f5192e81 [Partial Hydration] Dispatching events should not work until hydration commits (#16532)
* Refactor a bit to use less property access

* Add test for invoking an event before mount

* Add Hydration effect tag

This is equivalent to a "Placement" effect in that it's a new insertion
to the tree but it doesn't need an actual mutation.

It is only used to determine if a subtree has actually mounted yet.

* Use the Hydration flag for Roots

Previous roots had a Placement flag on them as a hack for this case but
since we have a special flag for it now, we can just use that.

* Add Flare test
2019-08-22 08:46:20 -07:00
Brian Vaughn
bf9415834f Fixed outdated extension popup wording 2019-08-21 14:28:57 -07:00
Brian Vaughn
6dda816102 Remove emoji prefix from Firefox extension tab labels
Firefox adds these already for React, so the extra emoji character was confusing. For now, we still prepend it for Chrome
2019-08-21 14:23:51 -07:00
Brian Vaughn
79bda69d88 Renamed DevTools Jest config to be more concistent with others 2019-08-21 13:40:24 -07:00
Dan Abramov
8a01b50fc3 eslint-plugin-react-hooks@2.0.1 2019-08-21 21:40:20 +01:00
Dan Abramov
3ed289b3b1 Clear canceled task node early (#16403) 2019-08-21 19:49:22 +01:00
Dan Abramov
0672829053 Bump ESLint plugin to 2.0 (#16528) 2019-08-21 19:14:34 +01:00
Nicolas Gallagher
2559111c21 [react-events] Rely on 'buttons' rather than 'button' (#16479)
The semantics of 'button' on events differs between PointerEvent and
MouseEvent, whereas they are the same for 'buttons'. Furthermore, 'buttons'
allows developers to determine when multiple buttons are pressed as the same
time.

https://w3c.github.io/pointerevents/#the-button-property
2019-08-21 10:07:15 -07:00
Dan Abramov
c433fbb593 Revert "Revert "[ESLint] Forbid top-level use*() calls (#16455)"" (#16525)
* Revert "Revert "[ESLint] Forbid top-level use*() calls (#16455)" (#16522)"

This reverts commit 507f0fb372.

* Update RulesOfHooks.js
2019-08-21 15:43:31 +01:00
Sunil Pai
507f0fb372 Revert "[ESLint] Forbid top-level use*() calls (#16455)" (#16522)
This reverts commit 96eb703bbf.
2019-08-21 10:20:34 +01:00
Brian Vaughn
66c9fedc34 Flow fixes 2019-08-20 13:33:33 -07:00
Brian Vaughn
fe943c339d Add custom DevTools Flow definitions to shared flowconfig 2019-08-20 11:37:45 -07:00
Brian Vaughn
2e549efae5 Moved DevTools custom Flow definitions 2019-08-20 11:37:31 -07:00
Brian Vaughn
4da836af71 Merged changes from 4.0.0 -> 4.0.5 from DevTools fork 2019-08-20 11:34:51 -07:00
Brian Vaughn
3ad50710a7 Merge branch 'source' of github.com:bvaughn/react-devtools-experimental 2019-08-20 11:00:02 -07:00
Brian Vaughn
833f206348 Merge branch 'master' into devtools-v4-merge 2019-08-20 10:41:38 -07:00
bbolek
efa5dbe7a5 Update CHANGELOG.md (#16439)
* Update CHANGELOG.md

Fixed typo
2019-08-20 09:51:01 -07:00
Heaven
da0a47bec3 fix typo in CHNAGELOG.md (#16447) 2019-08-20 09:48:03 -07:00
Morgan McCauley
69aafbf4df Fix spelling in react-devtools CHANGELOG.md (#16448) 2019-08-20 09:47:18 -07:00
Brian Vaughn
2843a1556e Fixed invalid object-assign version (4.0.4 -> 4.0.1) 2019-08-20 09:45:09 -07:00
Brian Vaughn
aa56fe34ac Improved GitHub issue repro instructions prompt 2019-08-20 09:44:41 -07:00
Sebastian Markbåge
c80678c760 Add "hydrationOptions" behind the enableSuspenseCallback flag (#16434)
This gets invoked when a boundary is either hydrated or if it is deleted
because it updated or got deleted before it mounted.
2019-08-19 13:26:39 -07:00
Dan Abramov
2d68bd0960 Fix message loop behavior when host callback is cancelled (#16407)
* Add a regression test for cancelCallback with message loop

* If there's nothing scheduled, we're not running

* Add more tests from #16271
2019-08-19 21:20:21 +01:00
Dan Abramov
96eb703bbf [ESLint] Forbid top-level use*() calls (#16455)
* Add a way to skip/only tests to RulesOfHooks test

* [ESLint] Forbid top-level use*() calls

* Add a regression test for logical expressions

This is not a change. Just adding more coverage.
2019-08-19 19:54:06 +01:00
Dan Abramov
56f93a7f38 Throw on unhandled SSR suspending (#16460)
* Throw on unhandled SSR suspending

* Add a nicer message when the flag is off

* Tweak internal refinement error message
2019-08-19 19:53:02 +01:00
Dominic Gannaway
dce430ad92 [Flare] Rework the responder dispatching/batching mechanism (#16334) 2019-08-19 19:22:46 +01:00
Brian Vaughn
6ae6a7c020 Updated React DevTools changelog for 4.0.5 2019-08-19 09:28:10 -07:00
Brian Vaughn
5441b094a4 4.0.4 -> 4.0.5 2019-08-19 09:26:55 -07:00
Nicolas Gallagher
56d1b0fb59 [react-events] DOM event testing library (#16433)
This patch formalizes the mock native events and event sequences used in unit tests.

The `createEventTarget` function returns an object that can be used to dispatch native event sequences on the target without having to manually do so across all the scenarios we need to account for. Unit tests can be written as if we were only working with PointerEvent, but they will dispatch realistic native event sequences based on the execution environment (e.g., is PointerEvent supported?) and pointer type.

```
describe.each(environments)('Suite', (hasPointerEvents) => {
  beforeEach(() => {
    // setup
  });

  test.each(pointerTypes)('Test', (pointerType) => {
    const target = createEventTarget(node);
    target.pointerdown({pointerType});
    expect(callback).toBeCalled();
  });
});
```

Every native event that is dispatched now includes a complete object by default. The properties of the events can be customized. Properties that shouldn't be relied on in responder implementations are excluded from the mock native events to ensure tests will fail. Equivalent properties are normalized across different event types, e.g., 'pointerId' is converted to 'identifier' before a TouchEvent is dispatched.
2019-08-19 09:21:55 -07:00
Brian Vaughn
01b1e7e2cf Alpha-sort props/state/context keys 2019-08-19 09:17:52 -07:00
Brian Vaughn
d2456c7572 Fixed standalone target not properly serving backend over localhost:8097 2019-08-19 07:36:41 -07:00
Brian Vaughn
14c2eab7c3 Resolved Yarn conflict for object-assign 2019-08-19 07:04:47 -07:00
Brian Vaughn
e89c19d16c Added DevTools 4.0.4 CHANGELOG entry 2019-08-18 08:55:49 -07:00
Brian Vaughn
3c6a219466 4.0.3 -> 4.0.4 2019-08-18 08:45:52 -07:00
Brian Vaughn
4697f5b379 Profiler bugfix for filtering out all commits after selecting a fiber 2019-08-18 08:34:40 -07:00
Brian Vaughn
d97af798d2 Updated DevTools CHANLOGE to add an unreleased change 2019-08-17 21:19:00 -07:00
Brian Vaughn
95ca079556 Fixed standalone bug that prevented backend from being served over localhost:8097 2019-08-17 21:11:10 -07:00
Brian Vaughn
21e793fb4f Added 4.0.1, 4.0.2, and 4.0.3 changelog entries (#16438)
* Added 4.0.1, 4.0.2, and 4.0.3 changelog entries
* Added entry about Map/Set/Immutable
2019-08-17 11:47:38 -07:00
Brian Vaughn
95ffd3ccf8 4.0.2 -> 4.0.3 2019-08-17 11:31:31 -07:00
Brian Vaughn
2935d6a18d Unserializable data type fix for standalone shell 2019-08-17 11:31:20 -07:00
Brian Vaughn
ce65df7092 Added support for unserializable types (e.g. Set/Map, Immutable) 2019-08-17 10:20:26 -07:00
Brian Vaughn
f66a20f439 Caps lock bug template request for repro steps :) 2019-08-16 14:47:55 -07:00
Brian Vaughn
69b2ecc531 Added explicit (empty) label next to empty arrays and objects 2019-08-16 13:47:09 -07:00
Brian Vaughn
024bac4263 Support single-quote strings in style editor 2019-08-16 13:35:30 -07:00
Brian Vaughn
74f4a3f972 Improved editing props demo experience for TODO list 2019-08-16 13:15:16 -07:00
Brian Vaughn
f616613059 Display hook values for components that only use context 2019-08-16 11:33:28 -07:00
Brian Vaughn
454157dd66 Multi-renderer profiling improvements
Add support for mixed v15/v16 renderers that previously caused profiling to fail with 'profiling not supported by this renderer' type errors
2019-08-16 11:25:44 -07:00
Brian Vaughn
49399aa3e7 Prettier 2019-08-16 09:05:26 -07:00
Brian Vaughn
5e043adba7 Added Set+Map to dev shell, even though we don't support deep inspecting them yet 2019-08-16 09:05:21 -07:00
Dan Abramov
c1d3f7f1a9 [DevTools Changelog] Add a note on 4.0.2 2019-08-16 16:15:19 +01:00
Brian Vaughn
2bcc6c6d04 4.0.1 -> 4.0.2 2019-08-15 17:35:30 -07:00
Brian Vaughn
527fc4a63f Refactored to remove need for new webNavigation permission 2019-08-15 17:34:34 -07:00
Brian Vaughn
c100cc7b31 4.0.0 -> 4.0.1 2019-08-15 16:29:13 -07:00
Brian Vaughn
545de6f02e Removed some unnecessary manifest permissions 2019-08-15 16:28:10 -07:00
Dan Abramov
6f86294e68 [DevTools Changelog] Add a note about restoring selection (#16409)
Also a tiny nit, "inline" spelling seems more common in this context. My eyes stumbled at it on every read.
2019-08-15 23:11:37 +01:00
Brian Vaughn
d0dcbe5594 Changed version name string to show version and date. Moved commit number into description string. 2019-08-15 14:38:16 -07:00
Brian Vaughn
0763c48ed8 Bumped all versions to 4.0.0 2019-08-15 14:28:09 -07:00
Brian Vaughn
732f3a6ef1 4.0.0-alpha.9 -> 4.0.0-alpha.10 2019-08-15 11:26:04 -07:00
Brian Vaughn
600c57a9b9 Added OVERVIEW.md and updated CHANGELOG to point to it (#16405) 2019-08-15 11:22:11 -07:00
Brian Vaughn
db9e5c9715 Updated all GitHub links to point to React repo 2019-08-15 11:17:59 -07:00
Brian Vaughn
9b5985b3c1 Added release date to DevTools CHANGELOG 2019-08-15 10:40:59 -07:00
Nicolas Gallagher
ebd1f5ddb0 [react-events] Press: improve test coverage (#16397)
1. Run the tests in both an environment without PointerEvent and one with PointerEvent.
2. Improve test coverage to include both mouse and touch pointers.
3. Change 'Press' so that it only listens to either pointer events or fallbacks events.
2019-08-15 10:28:00 -07:00
Brian Vaughn
85fbe3be3f Merge branch 'master' into devtools-v4-merge 2019-08-15 10:14:34 -07:00
Brian Vaughn
a9304e79d4 Add DevTools package placeholder package.json 2019-08-15 10:12:27 -07:00
Brian Vaughn
6edff8f5e1 Added CHANGELOG and READMEs for DevTools v4 NPM packages (#16404) 2019-08-15 10:06:16 -07:00
Brian Vaughn
7ce229d3b0 Made some incremental progress on Jest tests 2019-08-15 09:53:22 -07:00
Brian Vaughn
4c4f5fd27f Disable @babel/plugin-transform-block-scoping "throwIfClosureRequired" option for tests 2019-08-14 19:04:43 -07:00
Brian Vaughn
41db902ed4 Removed unused __TEST__ files 2019-08-14 19:03:32 -07:00
Brian Vaughn
a6aba5a587 Add explicit MIT license file (previously only in package.json) 2019-08-14 17:04:05 -07:00
Brian Vaughn
9ec9938ff4 print-warnings script should ignore DevTools packages 2019-08-14 14:02:12 -07:00
Brian Vaughn
a473dca59e Merge branch 'master' into devtools-v4-merge 2019-08-14 14:01:46 -07:00
Brian Vaughn
868d02d6c6 Added better error reporting for print-warnings errors (#16394) 2019-08-14 14:01:29 -07:00
Dan Abramov
4ba1412305 Revert "[Scheduler] Profiling features (#16145)" (#16392)
This reverts commit a34ca7bce6.
2019-08-14 20:02:41 +01:00
Brian Vaughn
4078167255 Removed (no longer necessary) node->node-events mapping 2019-08-14 11:43:59 -07:00
Brian Vaughn
d7ca8847f5 Add build-info.json to package files array for non-private DT packages 2019-08-14 11:40:09 -07:00
Brian Vaughn
39209dc5b5 Update react-devtools-inline to embed react-debug-tools since it's not published yet 2019-08-14 11:37:48 -07:00
Brian Vaughn
45dff31a75 Patched up react-devtools-core Webpack configs 2019-08-14 11:22:28 -07:00
Brian Vaughn
58b39c60db Fixed web extensions 2019-08-14 10:33:33 -07:00
Brian Vaughn
30b8ef3756 Iterated on Webpack configs until I got the inline and shell packages seemingly working 2019-08-14 09:24:35 -07:00
Brian Vaughn
44e410900d Merged master (with events -> legacy-events package rename) 2019-08-14 07:35:49 -07:00
Brian Vaughn
b1a03dfdc8 Rename legacy "events" package to "legacy-events" (#16388)
* Renamed 'events' package to 'legacy-events'
* Updated 'events' references to point to 'legacy-events'
2019-08-14 07:32:42 -07:00
Hristo Kanchev
9e64bf18e1 [eslint-plugin-react-hooks] Fixed crash when referencing arguments in arrow functions. (#16356)
* Fixed issue with def being undefined while referencing arguments.

* Removed todo comment.

* Skip exhaustive deps check if def is null.

* Fixed code formatting in ExhaustiveDeps.

* Removed unneeded comment in ExhaustiveDeps.
2019-08-14 14:44:06 +01: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
Simen Bekkhus
5fa99b5aa6 chore: add eslint-plugin-jest's valid-expect rule (#16332)
* chore: add eslint-plugin-jest's valid-expect rule

* update assertion
2019-08-14 11:51:01 +01:00
Brian Vaughn
441d014cef Cleaned up some extnesions build script stuff 2019-08-13 22:15:38 -07:00
Brian Vaughn
380da5fccc Moved OVERVIEW 2019-08-13 22:09:20 -07:00
Brian Vaughn
b73e293cc5 Moved CHANGELOG 2019-08-13 22:05:45 -07:00
Brian Vaughn
ac2e861fbe Fixed a bunch of Lint issues 2019-08-13 21:59:07 -07:00
Andrew Clark
a34ca7bce6 [Scheduler] Profiling features (#16145)
* [Scheduler] Mark user-timing events

Marks when Scheduler starts and stops running a task. Also marks when
a task is initially scheduled, and when Scheduler is waiting for a
callback, which can't be inferred from a sample-based JavaScript CPU
profile alone.

The plan is to use the user-timing events to build a Scheduler profiler
that shows how the lifetime of tasks interact with each other and
with unscheduled main thread work.

The test suite works by printing an text representation of a
Scheduler flamegraph.

* Expose shared array buffer with profiling info

Array contains

- the priority Scheduler is currently running
- the size of the queue
- the id of the currently running task

* Replace user-timing calls with event log

Events are written to an array buffer using a custom instruction format.
For now, this is only meant to be used during page start up, before the
profiler worker has a chance to start up. Once the worker is ready, call
`stopLoggingProfilerEvents` to return the log up to that point, then
send the array buffer to the worker.

Then switch to the sampling based approach.

* Record the current run ID

Each synchronous block of Scheduler work is given a unique run ID. This
is different than a task ID because a single task will have more than
one run if it yields with a continuation.
2019-08-13 19:01:17 -07:00
Lee Byron
56636353d8 Partial support for React.lazy() in server renderer. (#16383)
Provides partial support for React.lazy() components from the existing PartialRenderer server-side renderer.

Lazy components which are already resolved (or rejected), perhaps with something like `react-ssr-prepass`, can be continued into synchronously. If they have not yet been initialized, they'll be initialized before checking, opening the possibility to exploit this capability with a babel transform. If they're pending (which will typically be the case for a just initialized async ctor) then the existing invariant continues to be thrown.
2019-08-13 18:51:20 -07:00
Sebastian Markbåge
6fbe630549 [Partial Hydration] Attempt hydration at a higher pri first if props/context changes (#16352)
* Test that we can suspend updates while waiting to hydrate

* Attempt hydration at a higher pri first if props/context changes

* Retrying a dehydrated boundary pings at the earliest forced time

This might quickly become an already expired time.

* Mark the render as delayed if we have to retry

This allows the suspense config to kick in and we can wait for much longer
before we're forced to give up on hydrating.
2019-08-13 18:26:21 -07:00
Brian Vaughn
51626ae2f9 Prettier 2019-08-13 18:12:19 -07:00
Brian Vaughn
f7afe1b864 Moved shell fixture into packages/react-devtools-shell 2019-08-13 18:11:59 -07:00
Brian Vaughn
183f96f2ac Prettier 2019-08-13 17:58:03 -07:00
Brian Vaughn
edc46d7be7 Misc Flow and import fixes
1. Fixed all reported Flow errors
2. Added a few missing package declarations
3. Deleted ReactDebugHooks fork in favor of react-debug-tools
2019-08-13 17:53:28 -07:00
Brian Vaughn
08743b1a8e Reorganized folders into packages/* 2019-08-13 15:59:43 -07:00
Dan Abramov
e0a521b02a Make component stack last argument for deprecation warnings (#16384) 2019-08-13 23:25:03 +01:00
Dan Abramov
1fd3906e92 Remove "Waiting for async callback" User Timing measurement (#16379)
* Remove "Waiting for async callback" User Timing measurement

* Fix User Timing in PROD mode
2019-08-13 22:03:29 +01:00
lunaruan
89bbffed6e Cleanup Babel PR (ReactFreshPlugin) (#16340)
* fix babel 7 issues

* fix babel 7 issues
2019-08-13 21:18:40 +01:00
Dan Abramov
dc3160887b [CI] Disable coverage (#16380)
Looks like it's broken. Don't know if this will work to disable it while we figure out why?
2019-08-13 21:11:51 +01:00
Brian Vaughn
ec7ef50e8b Reorganized things again into packages 2019-08-13 11:37:25 -07:00
Brian Vaughn
7cabb3946e Reorganized fixtures 2019-08-13 11:11:25 -07:00
Brian Vaughn
c8922c3dbf Updated yarn.lock file 2019-08-13 11:08:40 -07:00
Brian Vaughn
9c825b59f1 Moved dev shell into fixtures/devtools 2019-08-13 11:05:37 -07:00
Brian Vaughn
65b93cd165 Merge remote-tracking branch 'devtools-merge/master' into devtools-v4-merge 2019-08-13 10:46:18 -07:00
Brian Vaughn
56b1c20cf0 Reorganized to avoid merge conflicts with React repo folder structure 2019-08-13 10:33:56 -07:00
Brian Vaughn
e3ac9d219d Merging DevTools fork 2019-08-13 10:10:41 -07:00
Brian Vaughn
848327760f Initializing empty merge repo 2019-08-13 10:09:17 -07:00
Andrew Clark
21d6395a14 Add test case for #16359 (#16371) 2019-08-12 19:00:50 -07:00
Sebastian Markbåge
a29adc9f62 Dehydrated suspense boundaries in suspense list (#16369)
If we get an insertion after a boundary, that has not yet been hydrated,
we take our best guess at which state the HTML is showing.

isSuspenseInstancePending means that we're still waiting for more server
HTML before we can hydrate. This should mean that we're showing the
fallback state.

isSuspenseInstanceFallback means that we want to client render something.
That most likely means that the server was unable to render and is
displaying a fallback state in this slot.

Adds tests to ensure that dehydrated components don't consider the force
flag.
2019-08-12 16:28:02 -07:00
Sebastian Markbåge
50addf4c0e Refactor Partial Hydration (#16346)
* Move dehydrated to be child of regular SuspenseComponent

We now store the comment node on SuspenseState instead and that indicates
that this SuspenseComponent is still dehydrated.

We also store a child but that is only used to represent the DOM node for
deletions and getNextHostSibling.

* Move logic from DehydratedSuspenseComponent to SuspenseComponent

Forked based on SuspenseState.dehydrated instead.

* Retry logic for dehydrated boundary

We can now simplify the logic for retrying dehydrated boundaries without
hydrating. This is becomes simply a reconciliation against the dehydrated
fragment which gets deleted, and the new children gets inserted.

* Remove dehydrated from throw

Instead we use the regular Suspense path. To save code, we attach retry
listeners in the commit phase even though technically we don't have to.

* Pop to nearest Suspense

I think this is right...?

* Popping hydration state should skip past the dehydrated instance

* Split mount from update and special case suspended second pass

The DidCapture flag isn't used consistently in the same way. We need
further refactor for this.

* Reorganize update path

If we remove the dehydration status in the first pass and then do a second
pass because we suspended, then we need to continue as if it didn't
previously suspend. Since there is no fragment child etc.

However, we must readd the deletion.

* Schedule context work on the boundary and not the child

* Warn for Suspense hydration in legacy mode

It does a two pass render that client renders the content.

* Rename DehydratedSuspenseComponent -> DehydratedFragment

This now doesn't represent a suspense boundary itself. Its parent does.

This Fiber represents the fragment around the dehydrated content.

* Refactor returns

Avoids the temporary mutable variables. I kept losing track of them.

* Add a comment explaining the type.

Placing it in the type since that's the central point as opposed to spread
out.
2019-08-12 15:58:38 -07:00
Andrew Clark
c2034716a5 Fix typo in error code map (#16373)
"responer" -> "responder"

I also removed an unused error code that never shipped.
2019-08-12 14:56:09 -07:00
Andrew Clark
62b04cfa75 Remove unused import
That's why you wait for the lint job to finish, Andrew!!!!!!
2019-08-12 14:35:33 -07:00
Andrew Clark
3eeb645515 Remove flag that reverts #15650 (#16372)
The change in #15650 has fully rolled out, so we can remove the flag
that reverts it.
2019-08-12 14:31:12 -07:00
Sebastian Markbåge
2716d91ec4 Reset didReceiveUpdate in beginWork (#16359)
This is a bad bug. It means that we sometimes inherit
didReceiveUpdate from a previous component's begin.

Effectively this only means that we're overrendering in some cases.

We should refactor to get rid of this as a global flag.
2019-08-12 14:16:25 -07:00
Nicolas Gallagher
9449f8bf39 [react-events] Fix keyboard responder test (#16368) 2019-08-12 13:51:00 -07:00
Brian Vaughn
6eb04b2b16 4.0.0-alpha.8 -> 4.0.0-alpha.9 2019-08-12 11:34:00 -07:00
Brian Vaughn
2f1c100e7c Misc. Profiler tweaks
* Disabled (with a follow up TODO) the  call in the reload-and-profile toggle.
* Disabled reload-and-profile in Firefox extension for now, since it was triggering a disconnected port error.
* Fixed Safari layout bug that caused profiler charts to be hidden.
2019-08-12 11:13:38 -07:00
Brian Vaughn
8fa608d9ab Fixed a selection-sync edge case for Elements/Components tabs 2019-08-12 10:31:50 -07:00
Nicolas Gallagher
107521a952 [react-events] Focus/FocusWithin responders with fallbacks (#16343)
Separate the PointerEvent and fallback implementations.
Fix the unit tests to cover both PointerEvent and non-PointerEvent environments.
Fix the focus-visible related callbacks to get called when keys other than "Tab" are used.
2019-08-12 10:10:51 -07:00
Brian Vaughn
8001b6432c Fixed raw-loader + Jest problem 2019-08-12 08:49:26 -07:00
Brian Vaughn
b5195a5f16 Fixed a couple of edge case styling and layout issues I noticed while testing the inline target 2019-08-12 08:26:48 -07:00
Desmond Brand
7a7e792a6f Make SchedulerMinHeap flow strict (#16351)
@acdlite while browsing Twitter, I saw [an opportunity][1] to do
something more productive than browsing Twitter.

[1]: https://twitter.com/acdlite/status/1160247965908234240

Test plan:

`yarn flow-ci`, `yarn test-prod`, `yarn lint`
2019-08-10 13:44:23 -07:00
Andrew Clark
e349da19b8 [Scheduler] Temporarily remove wrapper function (#16345)
This code is being compiled incorrectly by something in the Facebook
build pipeline. I'm removing it temporarily to unblock the sync while
we investigate.
2019-08-09 18:08:29 -07:00
Brian Vaughn
5b007573ac Release script supports publishing a subset of packages (#16338)
Release script supports publishing a subset of packages (#16338)
2019-08-09 13:12:00 -07: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
Nicolas Gallagher
07a02fb80d [react-events] Refactor unit tests for Hover (#16320)
**Problem**

The existing responders listen to pointer events by default and add fallback events if PointerEvent is not supported. However, this complicates the responders and makes it easy to create a problematic unit test environment. jsdom doesn't support PointerEvent, which means that the responders end up listening to pointer events *and* fallback events in unit tests. This isn't a direct problem in production environments, because no browser will fire pointer events if they aren't supported. But in the unit test environment, we often dispatch event sequences taken from browsers that support pointer events. This means that what we're often testing is actually a (complex) scenario that cannot even occur in production: a responder that is listening to and receives both pointer events and fallback events. Not only does this risk making responders more complicated to implement but it could also hide bugs in implementations.

**Response**

Implement the responders so that they're only listening to *either* pointer events *or* fallback events, never both. This should make the default pointer events implementations significantly simpler and easier to test, as well as free to rely on the complete PointerEvents API. In the future it should also make DCE easier for target environments that are known to support PointerEvents, as we can use build tools with an equivalent of the runtime check. The fallback events (touch and mouse) need to coexist and be resilient to browser emulated events. Our unit tests should express a suite of high-level interactions that can be run in environments with and without PointerEvents support.
2019-08-09 10:53:49 -07:00
Sunil Pai
f62b53d908 fix some missing assertions (#16336)
These were discovered by @SimenB in https://github.com/facebook/react/pull/16332. We weren't making actual assertions on some values. This PR makes the assertions, and fixes the tests.
2019-08-09 15:34:49 +01:00
Sunil Pai
b9faa3b092 [act] remove obsolete container element (#16312)
In a previous version of act(), we used a dummy dom element to flush effects. This doesn't need to exist anymore, and this PR removes it. The warning doesn't need to be there either (React will fire a wrong renderer act warning if needed).
2019-08-09 14:26:47 +01: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
Brian Vaughn
8d54038773 Add use-subscription to Rollup bundle config (#16326) 2019-08-08 18:52:08 -07: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
d77c6232d3 [Scheduler] Store Tasks on a Min Binary Heap (#16245)
* [Scheduler] Store Tasks on a Min Binary Heap

Switches Scheduler's priority queue implementation (for both tasks and
timers) to an array-based min binary heap.

This replaces the naive linked-list implementation that was left over
from the queue we once used to schedule React roots. A list was arguably
fine when it was only used for roots, since the total number of roots is
usually small, and is only 1 in the common case of a single-page app.

Since Scheduler is now used for many types of JavaScript tasks (e.g.
including timers), the total number of tasks can be much larger.

Binary heaps are the standard way to implement priority queues.
Insertion is O(1) in the average case (append to the end) and O(log n)
in the worst. Deletion is O(log n). Peek is O(1).

* Sophie nits
2019-08-08 16:18:05 -07:00
Andrew Clark
95767acf83 Bump deps in packages/**/package.json (#16325) 2019-08-08 14:50:11 -07:00
Brian Vaughn
6536973a00 Prepare use-subscription v1 for publishing (#16324) 2019-08-08 14:45:48 -07:00
Andrew Clark
85d05b3a4d Bump package.json versions 2019-08-08 14:24:39 -07:00
Dan Abramov
96cdf33ad3 Changelog for 16.9 (#16254)
* Changelog for 16.9 (TODO: add date)

* Update CHANGELOG.md

* Add date
2019-08-08 14:12:59 -07:00
Dominic Gannaway
d9fdec6cfe [Flare] Remove contextmenu logic from Press (#16322) 2019-08-08 21:42:01 +01:00
Dan Abramov
12be8938a5 [Fresh] Support multiple renderers at the same time (#16302) 2019-08-08 19:03:38 +01:00
Sebastian Markbåge
6f3c8332d8 Reset hydration state after reentering (#16306)
We might reenter a hydration state, when attempting to hydrate a boundary.
We need to ensure that we reset it to not hydrating once we exit it.
Otherwise the next sibling will still be in hydration mode.
2019-08-07 14:56:12 -07:00
Dominic Gannaway
028c07f89c Ensure Fundamental flags are added to more locations (#16311) 2019-08-07 14:48:30 +01:00
Dan Abramov
9dfe973b52 Nit: fix inconsistent spacing in a warning (#16310) 2019-08-07 14:30:21 +01:00
lunaruan
c4f0b93703 Warn when Using String Refs (#16217) 2019-08-07 00:10:19 -07:00
Dominic Gannaway
7c838a6450 [Flare] Adds support for hydrating host components with listeners (#16304) 2019-08-06 23:05:16 +01:00
Brian Vaughn
2eb3f4e9b8 README typofix 2019-08-06 10:45:16 -07:00
Brian Vaughn
2015a39c2e 4.0.0-alpha.7 -> 4.0.0-alpha.8 2019-08-06 10:22:12 -07:00
Nicolas Gallagher
ed49700796 [react-events] Separate the Focus/FocusWithin unit tests (#16298) 2019-08-06 09:16:21 -07:00
Nicolas Gallagher
23405c9c4c [react-events] Add ContextMenu responder (#16296)
A module for responding to contextmenu events. This functionality will be
removed from the Press responder in the future.
2019-08-06 09:16:05 -07:00
Brian Vaughn
e015e3d937 Added not about sync/batched root API being required 2019-08-06 08:57:34 -07:00
Brian Vaughn
2349f04478 Handle case where :root styles aren't (yet) applied when SettingsContext mounts
This fixes a possible bug in the inline shell where line-heights are NaN so the Tree (react-window List) gets created with a itemSize of NaN
2019-08-06 08:46:42 -07:00
Sebastian Markbåge
606f76b6e4 Fix hydration bug with nested suspense boundaries (#16288)
This happens in this case: `<!--$!--><!--$!-->...<!--/$--><!--/$-->...`

getNextHydratableInstanceAfterSuspenseInstance didn't take
SUSPENSE_FALLBACK_START_DATA or SUSPENSE_PENDING_START_DATA into account
so if a boundary was in one of those states, it wouldn't be considered to
push the stack of boundaries. As a result the first end comment was
considered the end but it really should've been the second end comment.

The next comment then would've been considered something that can be
skipped. However, since the logic in there considered all comments as
"hydratable", it was considered a hydratable node. Since it was considered
a node that didn't actually correspond to anything in the React tree it got
deleted.

The HTML is now `<!--$!--><!--$!-->...<!--/$-->...` and the trailing
content is now hydrated since it did match something.

Next, since this was client rendered, we're going to delete the suspended
boundary by calling clearSuspenseBoundary and then inserting new content.
However, clearSuspenseBoundary *is* aware of SUSPENSE_FALLBACK_START_DATA
and assumes that there must be another `<!--/$-->` after the first one.
As a result it deleted the trailing content from the DOM since it should
be part of the boundary. However, those DOM nodes were already hydrated in
the React tree. So we end up in an inconsistent state.

When we then try to insert the new content we throw as a result.

I think we would have recovered correctly if clearSuspenseBoundary and
getNextHydratableInstanceAfterSuspenseInstance had the *same* bug but
because they were inconsistent we ended up in a bad place.
2019-08-05 16:36:13 -07:00
Brian Vaughn
baac1dcc52 Inline package tweaks:
* Ignore messages from the DevTools browser extension.
* Cleanup/clarify README
2019-08-05 14:00:18 -07:00
Sunil Pai
a1dbb852c2 warn if you try to use act() in prod (#16282)
We have behaviour divergence for act() between prod and dev (specifically, act() + concurrent mode does not flush fallbacks in prod. This doesn't affect anyone in OSS yet)

We also don't have a good story for writing tests in prod (and what from what I gather, nobody really writes tests in prod mode).

We could have wiped out act() in prod builds, except that _we_ ourselves use act() for our tests when we run them in prod mode.

This PR is a compromise to all of this. We will log a warning if you try to use act() in prod mode, and we silence it in our test suites.
2019-08-05 13:01:05 -07:00
Ashwin Ramaswami
dc232e6774 chore: remove outdated comment about gcc (#16232) 2019-08-05 18:18:40 +01:00
Brian Vaughn
dc8580e64d New NPM package react-devtools-inline (#363) 2019-08-05 10:09:26 -07:00
Sam Horton
6f1e283b76 feat: match HOC display names during search (#360)
* feat: match HOC display names during search

* chore: update tests for new search logic
2019-08-05 09:44:48 -07:00
Brian Vaughn
6b3ae64598 Suppress known/expected warnings and errors in local DEV shell 2019-08-04 14:33:38 -07:00
Brian Vaughn
db8542ad97 Refactor inspect/select logic so that $r contains hooks data (#364)
* Refactor inspect/select logic so that  var contains hooks data
* Legacy renderer resets $r to null when inspecting non class/function element
2019-08-03 17:59:35 -07:00
Andrew Clark
6b565ce736 Rendering tasks should not jump the queue (#16284)
When React schedules a rendering task, it passes a `timeout` option
based on its expiration time. This is intended to avoid starvation
by other React updates. However, it also affects the relative priority
of React tasks and other Scheduler tasks at the same level, like
data processing.

This adds a feature flag to disable passing a `timeout` option to
Scheduler. React tasks will always append themselves to the end of
the queue, without jumping ahead of already scheduled tasks.

This does not affect the order in which React updates within a single
root are processed, but it could affect updates across multiple roots.

This also doesn't remove the expiration from Scheduler. It only means
that React tasks are not given special treatment.
2019-08-02 17:52:32 -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
644c9c4e1c [Flare] useListener -> useResponder (#362) 2019-08-02 10:14:25 -07:00
Brian Vaughn
9727f4e88f Don't let a DevTools or React internal error interfere with logging. 2019-08-02 09:39:39 -07:00
Brian Vaughn
abbaedd264 Updated Flow type for DevTools tab id 2019-08-02 09:27:13 -07:00
Andrew Clark
05dce7598a Fix priority of clean-up function on deletion (#16277)
The clean-up function of a passive effect (`useEffect`) usually fires
in a post-commit task, after the browser has painted. However, there is
an exception when the component (or its parent) is deleted from the
tree. In that case, we fire the clean-up function during the
synchronous commit phase, the same phase we use for layout effects.

This is a concession to implementation complexity. Calling it in the
passive effect phase would require either traversing the children of the
deleted fiber again, or including unmount effects as part of the fiber
effect list.

Because the functions are called during the sync phase in this case,
the Scheduler priority is Immediate (the one used for layout) instead
of Normal. We may want to reconsider this trade off later.
2019-08-01 22:17:59 -07:00
Sebastian Markbåge
a53f5cc22e [SuspenseList] Bug fix: Reset renderState when bailing out (#16278)
If there are adjacent updates we bail out of rendering the suspense list
at all but we may still complete the node. We need to reset the render
state in that case.

I restructured so that this is in the same code path so we don't forget it
in the future.
2019-08-01 22:02:28 -07:00
Dan Abramov
0c1ec049f8 Add a feature flag to disable legacy context (#16269)
* Add a feature flag to disable legacy context

* Address review

- invariant -> warning
- Make this.context and context argument actually undefined

* Increase test coverage for lifecycles

* Also disable it on the server is flag is on

* Make this.context {} when disabled, but function context is undefined

* Move checks inside
2019-08-02 01:21:32 +01:00
Sebastian Markbåge
95674af2ef Add test of scheduler overhead (#16260) 2019-08-01 17:13:39 -07:00
Dominic Gannaway
42794557ca [Flare] Tweaks to Flare system design and API (#16264) 2019-08-01 19:08:54 +01:00
Brian Vaughn
62e5fd57a1 NPM package versions 4.0.0-alpha.5 -> 4.0.0-alpha.6 2019-08-01 08:26:32 -07:00
Brian Vaughn
51a15e0e4d Added CHANGELOG entries for HOC badges and no in-line props 2019-08-01 07:56:10 -07:00
Brian Vaughn
aed31fdf12 Element keys are selectable text
Changed truncation to be CSS-driven, and enabled double-click selection of text, so that long keys could be copied from within the tree.
2019-07-31 14:48:39 -07:00
Brian Vaughn
11e7b1d290 Updated OVERVIEW doc 2019-07-31 14:22:43 -07:00
Brian Vaughn
e4ccafc099 Updated CHANGELOG based on Dan's feedback 2019-07-31 14:08:44 -07:00
Brian Vaughn
52b0c20a62 Added dynamic indentation to change log 2019-07-31 13:44:32 -07:00
Brian Vaughn
271aa75cf2 Removed the Profiler screenshot capture feature
This wasn't reliable because of browser extension API limitations and required serious throttling to avoid harming performance, so I've decided to just remove it entirely for now.
2019-07-31 11:36:01 -07:00
Brian Vaughn
4f8b7864ee Add "Welcome to the new DevTools" notification
This dialog is shown in the browser extension the first time a user views v4. It is off by default for the standalone extension, but can be enabled via a public API.
2019-07-31 11:22:51 -07:00
Brian Vaughn
c57d2a2901 Added CHANGELOG 2019-07-31 10:50:56 -07:00
Dominic Gannaway
b5af4fe3c6 Remove FocusScope (#16267) 2019-07-31 17:40:11 +01:00
Andrew Clark
3756167885 Add missing check to unmocked Scheduler warning (#16261)
The unmocked Scheduler warning doesn't actually check if Scheduler
is mocked.
2019-07-30 20:11:11 -07:00
Andrew Clark
f939df402c [act] Wrap IsThisRendererActing in DEV check (#16259)
* [act] Wrap IsThisRendererActing in DEV check

So that it doesn't leak into the production bundle. Follow-up to #16240.

* Disable Suspense fallback test in prod
2019-07-30 17:39:42 -07:00
Andrew Clark
f440bfd559 Bugfix: Effects should never have higher than normal priority (#16257)
* Bugfix: Priority when effects are flushed early

The priority of passive effects is supposed to be the same as the
priority of the render. This fixes a bug where the priority is sometimes
wrong if the effects are flushed early.

But the priority should really never be higher than Normal Priority.
I'll change that in the next commit.

* Effects never have higher than normal priority

Effects currently have the same priority as the render that spawns them.
This changes the behavior so that effects always have normal priority,
or lower if the render priority is lower (e.g. offscreen prerendering).

The implementation is a bit awkward because of the way `renderRoot`,
`commitRoot`, and `flushPassiveEffects` are split. This is a known
factoring problem that I'm planning to address once 16.9 is released.
2019-07-30 15:46:36 -07:00
Sunil Pai
db3ae32b8f flush fallbacks in tests (#16240)
In this PR, for tests (specifically, code inside an `act()` scope), we immediately trigger work that would have otherwise required a timeout. This makes it simpler to tests loading/spinner states, and makes tests resilient to changes in React.

For some of our tests(specifically, ReactSuspenseWithNoopRenderer-test.internal), we _don't_ want fallbacks to immediately trigger, because we're testing intermediate states and such. Added a feature flag `flushSuspenseFallbacksInTests` to disable this behaviour on a per case basis.
2019-07-30 19:12:06 +01:00
Sunil Pai
e6a0473c3c Warn when rendering tests in concurrent/batched mode without a mocked scheduler (#16207)
Concurrent/Batched mode tests should always be run with a mocked scheduler (v17 or not). This PR adds a warning for the same. I'll put up a separate PR to the docs with a page detailing how to mock the scheduler.
2019-07-30 19:00:18 +01:00
Nicolas Gallagher
e276a5e850 [Flare] Remove delay props from Hover (#16248)
Moving working with delays into user-space.
2019-07-30 09:29:43 -07:00
Nicolas Gallagher
1912b4a0f1 [Flare] Remove delay props from Press (#16247)
Moving working with delays into user-space.
2019-07-30 09:29:26 -07:00
Dominic Gannaway
55bc393f72 [Flare] Ensure we check for bad polyfill when creating responders (#16243) 2019-07-29 21:16:30 +01:00
Nicolas Gallagher
47656bf2a1 [Flare] Remove longpress from press responder (#16242)
Long press will move to a separate responder.
2019-07-29 13:12:12 -07:00
Dan Abramov
9914a19190 [Fresh] Transfer refs when remounting (#16241)
* Add a failing test for refs and remounting

* Transfer ref when remounting
2019-07-29 17:19:09 +01:00
Brian Vaughn
9a36e56d34 Added missing Flow header 2019-07-28 17:21:00 -07:00
Brian Vaughn
8e2134beee Re-add try/catch inside Agent's getIDForNode() 2019-07-28 08:42:21 -07:00
Philipp Spiess
82881ab261 Allow Inspecting Elements Within Iframes (#355)
This change adds support for element inspecting within `<iframe/>`s.

The iframes are kept in a Set so that we only append listeners once and
clean them up properly. I’ve run a few tests and it seems to behave as
expected.

The fixture includes a cross-origin iframe to make sure we do not error
in this case.
2019-07-28 08:40:02 -07:00
Brian Vaughn
50512a223b Reverted a Webpack config change that broke browser extension styles 2019-07-27 09:30:23 -07:00
Brian Vaughn
ca4aac5014 Tweaked recent search changes
1. Compare element indices rather than ids (since these don't necessarily correlate)
2. Restored previous behaior when new search text reduces the number of results past the currently-selected element.
2019-07-27 09:15:53 -07:00
Fanny
29a6bf2a7b Feature: tweak search behaviour (#353)
Merge PR #353 from @fanny

This change changes search beahvior to initially select the result nearest the currently selected element (rather than selecting the first result in the set).
2019-07-27 09:04:20 -07:00
Andrew Clark
75ab53b9e1 [scheduler] Yield many times per frame, no rAF (#16214)
Adds experimental flag to yield many times per frame using a message
event loop, instead of the current approach of guessing the next vsync
and yielding at the end of the frame.

This new approach forgoes a `requestAnimationFrame` entirely. It posts a
message event and performs a small amount of work (5ms) before yielding
to the browser, regardless of where it might be in the vsync cycle. At
the end of the event, if there's work left over, it posts another
message event.

This should keep the main thread responsive even for really high frame
rates. It also shouldn't matter if the hardware frame rate changes after
page load (our current heuristic only detects if the frame rate
increases, not decreases).

The main risk is that yielding more often will exacerbate main thread
contention with other browser tasks.

Let's try it and see.
2019-07-26 15:43:57 -07:00
Dominic Gannaway
0d7141dd49 [Flare] Fix SSR issue with serializing responders prop (#16227) 2019-07-26 22:47:37 +01:00
Andrew Clark
ed57bf8ed4 [Bugfix] Check tag before calling hook effects (#16215)
* Add failing test for #16215

Next commit fixes it.

* [Bugfix] Check tag before calling hook effects

TODO: Test that triggers this
2019-07-26 14:28:49 -07:00
Brian Vaughn
3b2905b690 NPM package versions 4.0.0-alpha.4 -> 4.0.0-alpha.5 2019-07-26 10:13:52 -07:00
Brian Vaughn
7385de9fc2 react-devtools-core standalone bugfix: prevent electron crash
CSS source maps require the style-loader to use URL.createObjectURL (rather than just a <style> tag). For some reason, this crashes Electron's webview process, which completely breaks the embedded extension inside of Nuclide and other Electron apps. This commit turns (CSS) source maps off for production builds to avoid this crash.
2019-07-26 10:13:07 -07:00
Belmin Bedak
858c84206e Don't hyphenate custom CSS properties for ReactDOMServer (#16167)
* Do not hyphenate custom CSS property

* Move check into the processStyleName fn

* Formatting

* add test

* Put isCustomProperty check after conditional return

* add test to `ReactDOMServerIntegration` and supress warning

* Don't indexOf twice

* Simpler fix
2019-07-26 18:06:24 +01:00
Sunil Pai
d412eec839 [act] flush work correctly without a mocked scheduler (#16223)
Not returning the value of flushPassiveEffects() in flushWork() meant that with async act, we wouldn't flush all work with cascading effects. This PR fixes that oversight, and adds some tests to catch this in the future.
2019-07-26 17:48:42 +01:00
Sophie Alpert
b43785e151 Update use-subscription README (#16216)
It was a little confusing that the question asked when NOT to use this package, then the answer says when to use it. I think this is a little better.
2019-07-25 19:30:55 -07:00
Andrew Clark
c0830a0e63 [Scheduler] Test browser implementation details (#16198)
The Scheduler implementation uses browser APIs like `MessageChannel`,
`requestAnimationFrame`, and `setTimeout` to schedule work on the main
thread. Most of our tests treat these as implementation details;
however, the sequence and timing of these APIs are not precisely
specified, and can vary wildly across browsers.

To prevent regressions, we need the ability to simulate specific edge
cases that we may encounter in various browsers.

This adds a new test suite that mocks all browser methods used in our
implementation. It assumes as little as possible about the order and
timing of events. The only thing it assumes is that
requestAnimationFrame is passed a frame time that is equal to or less
than the time returned by performance.now. Everything else can be
controlled at will.

It also includes Scheduler-specific invariants, e.g. only one rAF
callback can be scheduled at a time.

It overlaps slightly with the existing SchedulerDOM-test suite, which
also mocks the browser APIs, but exposes a higher-level set of testing
primitives. I will consolidate the two suites in a follow-up.
2019-07-25 15:53:14 -07:00
lunaruan
857deb2ed5 Warn when Using DefaultProps on Function Components (#16210)
As part of the process to deprecate defaultProps on function components (as per a larger proposal outlined in (https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md)), add a warning whenever someone does this.
2019-07-25 15:44:03 -07:00
Brian Vaughn
76c67399db Re-enabled packages backend build to be production mode (whoops) 2019-07-25 15:10:30 -07:00
Brian Vaughn
050cb8452d 4.0.0-alpha.3 -> 4.0.0-alpha.4 2019-07-25 10:26:52 -07:00
Dominic Gannaway
e0472709c8 [Flare] Adds Keyboard event responder (#16204) 2019-07-25 17:47:44 +01:00
Brian Vaughn
1e8aa8105a Re-enable "view source" button for standalone shell
But only do this if we can verify the element file path. This hopefully avoids the case where clicking the button does nothing because of an invalid/incomplete path.
2019-07-25 09:28:45 -07:00
Brian Vaughn
c6fb743910 Flow type cleanup 2019-07-25 09:13:45 -07:00
Dominic Gannaway
5b08f7b43f [Flare] Adds useListener implementation to ReactDebugHooks (#16205) 2019-07-25 16:55:39 +01:00
Dominic Gannaway
a7948e8342 [Flare] Remove the old EventComponent/EventTarget system (#354) 2019-07-25 08:45:59 -07:00
Dominic Gannaway
ed72f40257 [Flare] Remove references to EventComponent (#16206) 2019-07-25 16:41:26 +01:00
Brian Vaughn
270f34f7f0 Support new Flare hook, unstable_useListener 2019-07-25 08:21:41 -07: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
8d1c829019 Reverted style-prop hiding change because it caused a regression in the browser extension 2019-07-24 15:48:48 -07:00
Brian Vaughn
c7aff5503f 4.0.0-alpha.2 -> 4.0.0-alpha.3 2019-07-24 14:46:53 -07:00
Brian Vaughn
2e8b9fad36 Make style editor inputs more obvious resemble inputs 2019-07-24 14:43:29 -07:00
Brian Vaughn
9ae5e38f18 Add guard to ensure Profiler onRender prop is function before calling (#16197) 2019-07-24 14:20:56 -07:00
Brian Vaughn
4c610950a4 Hide "style" prop if we are showing the style editor
Also add react-native-web to test harness
2019-07-24 14:05:56 -07:00
Brian Vaughn
9a05e0b600 Disable view-source button in standalone mode if no project roots are provided 2019-07-24 13:36:51 -07:00
Brian Vaughn
722d366e9f Updated snapshot 2019-07-24 11:27:15 -07:00
Brian Vaughn
56b0017615 4.0.0-alpha.1 -> 4.0.0-alpha.2 2019-07-24 11:25:52 -07:00
Brian Vaughn
f74c89b145 Misc improvements based on user feedback from Tim
* Added shadow to modals
* Change default "collapse new nodes" to be disabled rather than enabled
* Changed setting label "Collapse newly added components by default" to "Expand component tree by default"
* Change CSS media query for settings popup to show labels at smaller size
* Hide "Inspect the matching DOM element" button (since it doesnt really serve a purpose in standalone)
* Fixed small size bug for settings icon (viewbox of 20x20 instead of 24x24)
* bugfix: window.addEventListener/window.removeEventListener is not defined in Hermes.
2019-07-24 11:25:11 -07:00
Brian Vaughn
13959aa8fb Removed accidental log statement 2019-07-24 11:13:30 -07:00
Benoit Girard
144dba1a11 Fix suspenseCallback type warning, add a test (#16194) 2019-07-24 18:32:00 +01:00
Dominic Gannaway
7ad221126f [Flare] Ensure Flare components are no-ops for TestRenderer (#16192) 2019-07-24 11:31:33 +01: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
Benoit Girard
42b75ab007 Add suspenseCallback feature for runtime tracing of loading states (#16134)
This adds a 'SuspenseCallback' feature flag. When the property is set on
a suspense component it will be called during the commit phase with a
set of the immediate thenable for this component. This will allow user
code to build runtime tracing of the cause for a suspense boundary.
2019-07-23 17:13:46 -07:00
Sunil Pai
c73e1f236f flush work on exiting outermost act(), with nested act()s from different renderers (#16181)
Given this snippet:
```jsx
    TestRenderer.act(() => {
      TestUtils.act(() => {
        TestRenderer.create(<Effecty />);
      });
    });
```
We want to make sure that all work is only flushed on exiting the outermost act().

Now, naively doing this based on actingScopeDepth would work with a mocked scheduler, where flushAll() would flush all work across renderers.

This doesn't work without mocking the scheduler though; and where flushing work only works per renderer. So we disable this behaviour for a non-mocked scenario. This seems like an ok tradeoff.
2019-07-24 00:20:28 +01:00
Dominic Gannaway
5098891193 [Flare] Redesign core event system (#16163) 2019-07-23 23:46:44 +01:00
Andrew Clark
19354db511 [Scheduler] Add names to inline functions (#16180)
Noticed when looking at the performance profiler with Luna that it's
hard to tell which event causes `performWorkUntilDeadline` to fire
because these functions are anonymous.
2019-07-23 11:08:24 -07:00
Andrew Clark
bff7abf6ba [Scheduler][Bugfix] Multiple rAFs in same frame (#16184)
Always sets `isRAFLoopRunning` back to false when an animation frame is
scheduled. Fixes a bug where two rAFs fire in the same frame, but the
second one exits and fails to schedule a new rAF.

Fixes bug observed in Safari.
2019-07-23 10:44:27 -07:00
Brian Vaughn
afb5991686 Enable profiler+tracing for test renderer (#16178)
This commit just brings the feature flags to parity with other renderers.
2019-07-23 08:20:12 -07:00
Dan Abramov
2237efcef9 [Fresh] Track unrecoverable errors (#16183)
* [Fresh] Track unrecoverable errors

* Only initial errors set the flag
2019-07-23 16:11:13 +01:00
Brian Vaughn
1178d57257 Fixed a module resolution issue and a syntax error from a bad merge 2019-07-23 07:46:19 -07:00
Nicolas Gallagher
bbd21066e6 [Flare] Press: fix keyboard interactions (#16179)
Prevents Spacebar from scrolling the window.
Prevents Enter from triggering a navigation if preventDefault is true.
Fixes the emulated mouse events test.
2019-07-22 18:16:40 -07: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
Andrew Clark
3f2cafe8be [WIP][Scheduler] Use rIC to post first callback (#16166)
Scheduler uses `requestAnimationFrame` to post tasks to the browser.
If this happens at the beginning of a frame, the callback might not
fire until the subsequent frame, even if the main thread is idle.

Our theory was that this wouldn't be an issue in practice, because once
the first rAF fires, we schedule the next rAF as early as possible in
that frame. Combined with our heuristic for computing frame deadlines,
we shouldn't get any idle time in between frames — only before the
*first* frame.

This reasoning holds true when you have a small number of large tasks,
such as the ones posted by React. The idle time before the task starts
is negligible relative to the lifetime of the entire task.

However, it does not hold if you have many small tasks posted over a
span of time, perhaps spawned by a flurry of IO events. In this case,
instead of single, contiguous rAF loop preceded by an idle frame, you
get many rAF loops preceded by many idle frames. Our new theory is that
this is contributing to poor main thread utilization during page loads.

To try to reclaim as much idle time as possible, this PR adds two
experimental flags. The first one adds a `requestIdleCallback` call to
start the rAF loop, which will fire before rAF if there's idle time left
in the frame. (We still call rAF in case there isn't. We start working
in whichever event fires first.)

The second flag tries a similar strategy using `setTimeout(fn, 0)`. If
the timer fires before rAF, we'll assume that the main thread is idle.

If either `requestIdleCallback` or `setTimeout` fires before rAF, we'll
immediately peform some work. Since we don't have a real frame time that
we can use to compute the frame deadline, we'll do an entire frame
length of work. This will probably push us past the vsync, but this is
fine because we can catch up during the next frame, by which point a
real rAF will have fired and the loop can proceed the same way it
does today.

Test plan: Try this on Facebook to see if it improves load times
2019-07-22 13:12:33 -07:00
Andrew Clark
2bd88e38aa [Scheduler] Bugfix: Cancelling a continuation (#16151)
Cancelling the original task should also cancel its continuation.
2019-07-22 13:10:33 -07:00
Brian Vaughn
ffb19346c7 NPM packages 4.0.0-alpha.0 -> 4.0.0-alpha.1 2019-07-22 11:19:53 -07:00
Dominic Gannaway
783b8f4ae1 [Flare] Ensure mouse events can use target to validate press (#16172) 2019-07-22 12:31:19 +01:00
Brian Vaughn
4b34a77d29 Improve Bridge Flow types (#352)
* Updated local fork of react-window
* Updated Fow 97 -> 103
* Lint ignore NPM dist
* Improved Bridge Flow types
2019-07-20 14:08:23 -07:00
Brian Vaughn
39ad101ea2 Removed reference to setDefaultThemeName() method
This functionality was added to v3 to support external changing of theme at runtime. This isn't supported in v4.
2019-07-20 09:28:09 -07:00
Brian Vaughn
33da657178 Make console override detectable (for RN YellowBox) 2019-07-20 08:05:08 -07:00
Dominic Gannaway
2c4d61e102 Adds experimental fundamental interface (#16049) 2019-07-19 22:20:28 +01:00
Brian Vaughn
167daf7a4a Updating NPM packages as 4.0.0-alpha.0 2019-07-19 10:09:49 -07:00
Brian Vaughn
abe75b0e39 Slight tweak to avoid setting an invalid numeric value in props editor 2019-07-19 09:19:03 -07:00
Brian Vaughn
f0a4b2f8e8 Merge branch 'fix-input-number-in-props' of https://github.com/koba04/react-devtools-experimental into koba04-fix-input-number-in-props 2019-07-19 09:16:26 -07:00
Brian Vaughn
0abaefb7c2 Cleanup legacy backend event listener if modern backend is detected 2019-07-19 09:02:30 -07:00
Brian Vaughn
dbbf30a332 Make my code PRETTIER 2019-07-18 16:37:57 -07:00
Brian Vaughn
67e749a73a Tweaked modal font size style 2019-07-18 16:28:20 -07:00
Brian Vaughn
bd0a0c58fd Tweaked modal title to better fit without wrapping 2019-07-18 16:26:27 -07:00
Brian Vaughn
249a2e043d Detect React Native v3 backend and show warning 2019-07-18 16:24:22 -07:00
Paul Shen
b4178af81b clean up nextEffect pointers (#16115) 2019-07-17 17:21:19 -07:00
Nicolas Gallagher
997154bcc7 [Flare] Add FocusWithin responder (#16152)
FocusWithin is implemented as a separate responder, which keeps both focus
responders simple and allows for easier composition of behaviours.
2019-07-17 15:17:13 -07:00
Brian Vaughn
9fb753b5cd Hardened logic around when and how to patch console methods 2019-07-17 15:08:34 -07:00
Dominic Gannaway
65b80fdd94 [Flare] Add Input event responder surface (#16148) 2019-07-17 21:04:41 +01:00
Brian Vaughn
cb3fb42129 Patch console to append component stacks (#348)
* Patch console.warn and console.error to auto-append owners-only component stacks.

This setting is enabled by default and will work for React Native even if no front-end DevTools shell is being used. The setting can be disabled via a new, persisted user preference though.
2019-07-17 11:12:39 -07:00
Brian Vaughn
ce883a19d8 useSubscription hook (#15022)
* Added use-subscription package with README
2019-07-16 15:59:37 -07:00
Moti Zilberman
c45c2c3a26 Move ReactFiberErrorDialog RN fork into RN itself (#16141) 2019-07-16 09:38:14 +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
424099da60 Inject getCurrentFiber() function to DevTools (#16133)
This returns the current value of ReactCurrentFiber and enables DevTools to append a custom (owner-only) component stack to warnings and errors in DEV mode.
2019-07-15 07:38:44 -07:00
Toru Kobayashi
41c00cb0cb fix to input a number value to props 2019-07-14 23:11:08 +09:00
Brian Vaughn
0f2fb5badf Standalone NPM packages and React Native support (#335)
* Add version 4 react-devtools and react-devtools-core packages which support both React Native and e.g. Safari or iframe DOM usage.
* Replaces typed operations arrays with regular arrays in order to support Hermes. This is unfortunate, since in theory a typed array buffer could be more efficiently transferred between frontend and backend for the web extension, but this never actually worked properly in v8, only Spidermonkey, and it fails entirely in Hermes so for the time being- it's been removed.
* Adds support for React Native (paper renderer)
* Adds a style editor for react-native and react-native-web
2019-07-13 10:05:04 -07:00
Brian Vaughn
9f395904c6 Inject ReactDebugCurrentFrame into DevTools so it can append component stacks to warnings in DEV mode (#16127) 2019-07-13 08:53:21 -07:00
Sebastian Markbåge
fcff9c57bc Add tail="hidden" option to SuspenseList (#16024)
* Move misaligned comment

* Add tail="hidden" option

* isShowingAnyFallbacks -> findFirstSuspended

* We can't reset Placement tags or we'll forget to insert them

* Delete hasSuspendedChildrenAndNewContent optimization
2019-07-12 15:55:47 -07: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
Andrew Clark
29b4559635 .watchmanconfig must be valid json (#16118)
faceworldproblems?
2019-07-11 19:01:02 -07:00
Nicolas Gallagher
ca4d78f9b6 [Flare] Press: fix middle-click handling (#16114)
Make sure the root events are removed after middle-click completes
2019-07-11 22:12:10 +01: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
Sebastian Markbåge
b7669044d9 Use Map instead of object as map in ReactNativeComponentTree (#16107)
Real Maps should now be used in RN JS engines. In theory this should
be faster (but might not actually be in practice), and it avoids hitting
upper bounds of property max counts.

We don't use these types of Maps in Fabric.
2019-07-10 19:11:36 -07:00
Andrew Clark
d2d9b1f701 [Scheduler] Support inferring priority from stack (#16105)
When executing a task, wraps the callback in an extra function whose
name includes the current priority level. Profiling tools with access
to function names can use this to determine the priority of the task.
2019-07-10 18:59:44 -07:00
Sebastian Markbåge
48f6594474 Add warning when single item or nested arrays are used with SuspenseList (#16094) 2019-07-10 11:07:28 -07:00
Nicolas Gallagher
2073a7144e [Flare] Press includes button type (#16100)
1. Allow auxillary button clicks (i.e., middle mouse button) to trigger 'onPressStart' and 'onPressEnd', but never 'onPress'.
2. Report the button type – 'primary' or 'auxillary' – on the press event.
2019-07-10 17:52:10 +01:00
Dominic Gannaway
23b8a25345 [Flare] Remove responder flags to simplify logic (#16084) 2019-07-09 15:05:45 +01:00
Eli White
8533c0a168 [Fabric] Add dispatchCommand to React Native renderers (#16085)
* Add dispatchCommand to the public export of the React Native renderers

* Fixup invalid check

* Prettier

* Prettier
2019-07-08 13:03:57 -07:00
Dominic Gannaway
2253bc81d0 [Flare] Switch from currentTarget model to responderTarget model (#16082) 2019-07-08 17:03:15 +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
Dominic Gannaway
aa519c17cc [Flare] Add currentTarget and unify RN and DOM codepaths (#16066) 2019-07-08 11:50:21 +01:00
Brian Vaughn
39a811debe Merge pull request #342 from marvinhagemeister/attach_configure
Fix reload-and-profile attach not configurable
2019-07-06 18:40:00 -04:00
fnll
35d2b3bb5e fix spelling error: resoltion -> resolution (#16055) 2019-07-05 16:08:13 +01:00
Vincent Riemer
bd72b04939 [Flare] Clear pressStart timeout on pointercancel (#16067) 2019-07-05 11:45:33 +01:00
Dominic Gannaway
c40075a72c [Flare] Remove capture phase Flare events (#16054) 2019-07-04 21:30:46 +01:00
Dominic Gannaway
786186c692 [Flare] createInitialState -> getInitialState (#16051) 2019-07-04 18:06:18 +01:00
Dominic Gannaway
c64f40d718 [Flare] Remove dead event target code (#16063) 2019-07-04 13:10:55 +01:00
Dominic Gannaway
e6bfa327da [Flare] Cleanup ReactFiberEvents-test (#16047) 2019-07-03 11:31:06 +01:00
Dominic Gannaway
b365ee2816 [Fire] Remove unused React fire fork (#16046) 2019-07-03 11:05:28 +01:00
Sunil Pai
b8f91e6649 [fail] reset IsThisRendererActing correctly (#16042)
* [fail] reset IsThisRendererActing correctly

I missed this in https://github.com/facebook/react/pull/16039. I'd pointed at the wrong previous state, corrupting it in further use. This PR fixes that, and adds a test to make sure it doesn't happen again.

* warn for unacted effects only in strict mode
2019-07-03 03:04:22 +01:00
Sunil Pai
bd846459d6 [fail] Only warn on unacted effects for strict / non sync modes (#16041)
* only warn on unacted effects for strict / non sync modes

(basically, when `fiber.mode !== 0b0000`)

Warnings on unacted effects may be too noisy, especially for legacy apps. This PR fires the warning only when in a non sync mode (concurrent/batched), or when in strict mode. This should make updating easier.

I also added batched mode tests to the act() suite.

* explicitly check for modes before warning, explicit tests for all modes
2019-07-03 01:29:45 +01:00
Dominic Gannaway
6b946ad9da [Flare] Add more functionality to Scroll event resonder (#16036) 2019-07-02 23:51:31 +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
Anton Korzunov
a865e4a642 Clone a custom hook node before use (#16019) 2019-07-02 17:54:10 +01:00
Dominic Gannaway
6cf2234a57 [Flare] Do not block mouse presses on scroll (#16033) 2019-07-02 16:58:46 +01:00
Sebastian Markbåge
5cb8f6f344 Add tail="collapsed" option to SuspenseList (#16007)
* Add tail="collapsed" option

* Fix issue with tail exceeding the CPU time limit

We used to assume that this didn't suspend but this branch happens in
both cases. This fixes it so that we first check if we suspended.

Now we can fix the tail so that it always render an additional fallback
in this scenario.
2019-07-01 19:56:34 -07:00
lunaruan
46bd11ac3e Flush sync bug (#16027)
* added flush sync test

* added code to run flushSync with ImmediatePriority

* added code to run flushSync with ImmediatePriority

* fixed flow error

* fixed flow error
2019-07-01 16:58:04 -07:00
Marvin Hagemeister
8e90194f7d Add comment about 3rd party integrations 2019-07-01 23:48:52 +02:00
Marvin Hagemeister
5ec387aa82 Mark reload-and-profile attach as configurable 2019-07-01 23:35:35 +02:00
Sebastian Markbåge
933c664ad6 SuspenseList Optimizations (#16005)
* Add a bunch of optimizations to SuspenseList

We now are able to bail out of reconciliation and splitting out the tail
during deep updates that hasn't changed the child props. This only
works while the list wasn't suspended before.

I also moved the second render of the "head" to the complete phase. This
cleans it up a bit for the tail collapsing PR.

For this second pass I also use a new technique of resetting the child
Fibers for the second pass. This is effectively a fast path to avoid
reconciling the children against props again.

* Move to didSuspend from SuspenseListState to the effectTag

The effectTag now tracks whether the previous commit was suspended.

This frees up SuspenseListState to be render-phase only state.

We use null to mean the default "independent" mode.

* Rename to SuspenseListState to SuspenseListRenderState

* Reuse SuspenseListRenderState across render passes

* Add optimization to bail out of scanning children if they can't be suspended

This optimized the deep update case or initial render without anything
suspending.

We have some information available to us that tell us if nothing has
suspended in the past and nothing has suspended this render pass.

This also fixes a bug where we didn't tag the previous render as having
suspended boundaries if we didn't need to force a rerender.

* rm printChildren

oops
2019-07-01 14:25:07 -07:00
Heaven
fbbbea16e1 fix word async -> concurrent (#15844) 2019-07-01 17:32:29 +01:00
Dominic Gannaway
eb2ace1281 [Flare] Bring Flare support to React Native Fabric (#15887) 2019-06-28 01:22:32 +01:00
Dominic Gannaway
9b0bd43550 [Flare] Re-label Flare flag (#16014) 2019-06-28 01:11:11 +01:00
Dominic Gannaway
8b88ac2592 [Flare] Remove event targets including TouchHitTarget (#16011) 2019-06-27 23:58:48 +01:00
Dan Abramov
f11540926d Handle changes at module boundaries (#16002) 2019-06-27 20:53:03 +01:00
Benedikt Meurer
915dfe6977 Slightly improve performance of hydration. (#15998)
* Slightly improve performance of hydration.

Avoid loading nodeType and data couple times from the same node in a row,
but instead load them only once, which will help engines to run this code
faster, especially during startup of the application. The general approach
is still not ideal, since hydrating this way forces the browser engine
to materialize JavaScript wrapper objects for all DOM nodes, even if they
are not interesting to hydration itself.

* Fix condition for COMMENT_NODEs.

* Improve general code readability
2019-06-27 07:23:14 -07:00
Dominic Gannaway
824e9bec7a [Flare] Fix issues with touch + pointer interactions (#15997) 2019-06-26 22:25:49 +01:00
Dominic Gannaway
dd93357aa0 [Flare] Move click handling back into target phase (#15993) 2019-06-26 20:44:44 +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
Brandon Dail
9b55bcfc6b [Flare] Add Hooks to event modules (#15953) 2019-06-26 08:47:21 +01:00
Ricky
20da1dae4b Fix error logging in getDerivedStateFromProps (#15797)
* Fix error logging in getDerivedStateFromProps

* Update tests, don't log for both error boundary methods

* Re-add change lost in rebase
2019-06-25 18:02:27 +01:00
Dominic Gannaway
6088a201e1 [Flare] Fix Press scroll cancellation handling (#15983) 2019-06-25 14:31:48 +01:00
Dominic Gannaway
fd601fb219 [Flare] Move all event responders to dom directory (#15981) 2019-06-25 09:32:20 +01:00
Veniamin Krol
827cbc4d00 Rename StatelessComponent to FunctionComponent in react-is/README.md (#15963) 2019-06-24 16:21:58 -07:00
Dan Abramov
d48db594ec eslint-plugin-react-hooks@1.6.1 2019-06-24 22:31:14 +01:00
Thomas Broyer
7439b48cf4 Add explicit support for ESLint 6.0.0 (#15974)
Preemptively update tests wrt 'parser' requiring an absolute
path rather than a package name, even though the project is
still using ESLint 4.

Fixes #15971
2019-06-24 22:30:12 +01:00
Sunil Pai
fce15f14d3 don't fire missing act() warnings for react-art (#15975)
* use toWarnDev for dom fixture tests

forks toWarnDev from root into fixture/dom, updates tes tests to use it

* disable act() warnings for react-art()

- For 'secondary' renderers like react-act, we don't want to fire missing act() warnings; the wrapping renderer will fire warnings anyway, and when it flushes, it flushes effects *across* renderers.

- I could have used isPrimaryRenderer as the flag, but this is marked as false for react-test-renderer, and we *do* want the warning to fire for it. Hence a new flag.

* add missing dependency `art` to fixtures/dom
2019-06-24 19:18:26 +01:00
Dominic Gannaway
20f3546963 [Flare] Ensure Press event hook does not execute side-effects (#15976) 2019-06-24 18:31:49 +01:00
Dan Abramov
d420d2ccb6 [Fresh] Retry failed roots on refresh (#15966)
* Retry failed roots on refresh

* Don't prevent retry after error -> render(null) special case

The check wasn't very resilient because in Concurrent Mode it looks like we can get further follow-up commits even if we captured an error. So we can't reliably distinguish the case where after an error you _manually_ rendered null.

Retrying on an edit after a tree failed _and_ you rendered null in the same tree seems fine. It's also very unlikely a pattern like this actually exists in the wild.
2019-06-24 16:54:54 +01:00
Brian Vaughn
844cdb22d6 Merge pull request #331 from trueadm/flare_displayName
[Flare] Update event component displayName
2019-06-24 07:48:24 -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
Dan Abramov
39b97e8eb8 Report refreshed families to the caller (#15957) 2019-06-22 23:57:54 +01:00
Dan Abramov
d271df5c99 Use function expression for custom Hook signature argument (#15956) 2019-06-22 11:54:22 +01:00
Andrew Clark
4189f712c1 [Scheduler] Increase max frame length to 300
Forgot to apply this change before merging.

https://github.com/facebook/react/pull/15959#discussion_r296429705
2019-06-22 01:38:19 -07:00
Andrew Clark
595c9414ba [Scheduler] Fix navigator.isInputPending call
Must be called as a method.
2019-06-22 00:50:13 -07:00
Andrew Clark
e7fcfe1047 [scheduler] Put isPendingInput behind a flag (#15962) 2019-06-22 00:46:27 -07:00
Andrew Clark
6568a79931 [Scheduler] requestPaint (#15960)
* [Scheduler] requestPaint

Signals to Scheduler that the browser needs to paint the screen. React
will call it in the commit phase. Scheduler will yield at the end of
the current frame, even if there is no pending input.

When `isInputPending` is not available, this has no effect, because we
yield at the end of every frame regardless.

React will call `requestPaint` in the commit phase as long as there's at
least one effect. We could choose not to call it if none of the effects
are DOM mutations, but this is so rare that it doesn't seem worthwhile
to bother checking.

* Fall back gracefully if requestPaint is missing
2019-06-22 00:15:09 -07:00
Andrew Clark
8d4ddd33ac [Scheduler] Yield less if there's no pending input (#15959)
At the end of each frame, Scheduler yields control of the main thread so
the browser can execute important tasks; most importantly, painting the
screen and responding to user input. There's some overhead involved in
regaining control of the main thread, so we'd like to yield as
infrequently as possible to keep the UI responsive.

The reason we yield on every frame is because there's no way for us to
know whether we're blocking user input.

`isInputPending` is an experimental browser API that gives us this
information. It tells us whether there's a pending user input, which
also means it tells us if there's *not* a pending user input. We can use
this signal to decide whether it's OK not to yield.

There's a max frame length after which we'll yield regardless, as a
precaution against blocking non-input tasks that we don't know about.
2019-06-22 00:05:38 -07: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
696609d49a [Fiber] Clear down dependencies during detachFiber (#15947) 2019-06-21 19:54:04 +01:00
Dominic Gannaway
a5ed2f98f9 [Flare] Guard against stateNode being null (#15952) 2019-06-21 19:14:03 +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
Andrew Clark
175111de72 Lazily initialize dependencies object (#15944)
Most fibers do not have events or context, so we save memory lazily
initializing this container node.

Follow-up from #15927
2019-06-20 20:12:22 -07: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
Nicolas Gallagher
6ff4c9de1c [Flare] Press: fix stale deactivation region state (#15931)
The responder region calculation logic wasn't updating the deactivation region
during the lifetime of an event instance, causing incorrect behaviour when the
current press ends outside the press target and if the press target has moved
since the last time the first-and-only time the deactivation region was
measured.
2019-06-20 17:10:54 -07:00
Dan Abramov
7a4c3e3b73 Make global names more obscure (#15941) 2019-06-20 20:20:09 +01:00
Sebastian Markbåge
270dc2e4de Add forwards and backwards options to SuspenseList (#15918)
* Add forwards option

* Add backwards option

* Add comment

* Add customized warning messages for case and typos

* Add some more tests for insertions and updates in start/middle/end
2019-06-20 11:03:47 -07:00
Dominic Gannaway
5368f7316c [Flare] Fix keyboard keyup regression (#15938) 2019-06-20 17:00:09 +01:00
Dan Abramov
3d0af2aea8 Don't consider require-like calls to be likely HOCs (#15940) 2019-06-20 16:13:18 +01:00
Dan Abramov
d4f384d25b [Fresh] Throw in prod and change annotation (#15939)
* Disable React Refresh Babel transform in prod

* Throw early if React Refresh runtime is imported in production

* @hot reset -> @refresh reset
2019-06-20 14:29:00 +01:00
Sunil Pai
ff91bfa58c [act] reset scope depth on synchronous errors (#15937)
* reset scope depth on synchronous errors

we weren't resetting the acting scope depth on sync errors thrown in the callback. this fixes that.

* typos

* add a test to make sure sync error propagate
2019-06-20 13:50:53 +01:00
Dominic Gannaway
e61c9e0a26 [Flare] Fix Press retention state regression (#15936) 2019-06-20 13:01:56 +01: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
Dan Abramov
e9d0a3ff25 [Fresh] Track mounted roots via DevTools Hook (#15928)
* Track mounted roots via DevTools Hook

* Add helper utilities to the runtime

These utilities will likely be needed by all module systems, so let's just put them here.

* Wrap more things in __DEV__

* Fix tests to also be DEV-only
2019-06-20 00:12:43 +01:00
Andrew Clark
35ef78de3e [Scheduler] Integrated timers (#15911)
Adds a `delay` option to `scheduleCallback`. When specified, the task is
not scheduled until after the delay has elapsed.

Delayed tasks are scheduled on a timer queue maintained by Scheduler,
instead of directly with the browser. The main benefit is to reduce the
number of native browser timers that Scheduler's `message` event handler
has to contend with; so, after yielding to the browser at the end of the
frame, Scheduler will more quickly regain control of the main thread.
Because we're able to flush the timer queue without yielding to browser
timer events, there's also less task switching overhead (though in the
absence of `isInputPending`, this is mostly a theoretical win since we
yield every frame regardless).

If the queue of non-delayed tasks is non-empty — that is, if there is
pending CPU bound work — Scheduler is able to avoid a browser timer
entirely by periodically checking its own timer queue while flushing
tasks (inside the `message` event handler). Once the CPU-bound work is
complete, if there are still pending delayed tasks, Scheduler will
schedule a single browser timer that fires once the earliest delay
has elapsed.
2019-06-19 16:05:07 -07:00
Andrew Clark
3af91eb8ce [Scheduler] Use continuation pattern for posting host callback (#15910)
* [scheduler] Internal rename: Callback -> Task

Rename Callback type to Task. Does not affect the public API, only
internal names, though eventually we'll probably want to align with the
WICG Main-thread Scheduling proposal
(https://github.com/WICG/main-thread-scheduling).

* [scheduler] flushFirstTask() -> flushTask(task)

Pass task as an argument to `flushTask` instead of using a module-
level variable.

* [scheduler] Add startTime field

This does not change any semantics, but in the future `startTime` may
represent a future time, to support delayed tasks.

* [Scheduler] Use continuation pattern for host cb

As I prepare to implement integrated timers, I noticed some
peculiarities in the Scheduler implementation that could afford to be
cleaned up.

This is a refactor and shouldn't affect any observable behavior; mostly
it removes some concepts that existed in earlier iterations of Scheduler
and are no longer needed.

The main change is to how the DOM implementation schedules an additional
callback before yielding to the main thread. It used to follow the same
code path for scheduling task; now it has its own branch directly
inside the message event handler. The special case for error handling
— where we call `postMessage` immediately without waiting for rAF —
has similarly been localized inside the catch block of the message
event handler.
2019-06-19 15:57:33 -07:00
Brian Vaughn
81e5e9be0b Updated @reach/tooltip to v0.2.2 for a bugfix 2019-06-19 15:43:15 -07:00
Dominic Gannaway
b62ae16429 [Flare] Rename createEventComponent -> createEvent (#15929) 2019-06-19 21:12:14 +01:00
Brian Vaughn
35600be1da Changed Chrome manifest version from 4.0.0.0 to 4.0.0 2019-06-19 11:06:36 -07:00
Nicolas Gallagher
f4e1ac8caf [Flare] Press events include defaultPrevented (#15916)
* Rename `disableContextMenu` to `preventContextMenu`
* Change the behaviour of `preventContextMenu` so that `onContextMenu` is still called when the native context menu is prevented.
2019-06-19 11:00:44 -07:00
Dominic Gannaway
89a0886872 [Flare] Update event component displayName 2019-06-19 17:43:15 +01:00
Dominic Gannaway
4a7a39b594 [Flare] Add RN build step for ReactTypes (#15926) 2019-06-19 13:27:10 +01:00
Christoph Nakazawa
0bd7551146 Remove mention of Prepack (#15922)
We aren't shipping Prepack anytime soon. FB-only: see D15585102.
2019-06-19 11:05:28 +01:00
Brian Vaughn
083bf8d98b Don't try to convert absolute paths to relative 2019-06-18 18:40:05 -07:00
Brian Vaughn
0e4005e0a1 Added command to build Chrome CRX 2019-06-18 15:44:22 -07:00
Dominic Gannaway
689beef6f5 [Flare] Move unstable_createEventComponent to ReactDOM (#15890) 2019-06-18 23:41:00 +01:00
Moti Zilberman
98454371a9 Construct Error at invariant call site for clearer stack traces (#15877) 2019-06-18 11:38:33 -07:00
Brian Vaughn
abc8ef3d5d Display unnamed custom hooks as 'Anonymous' 2019-06-18 11:37:29 -07:00
Nicolas Gallagher
f97b951666 [Flare] add disableContextMenu to Press (#15909) 2019-06-18 11:34:34 -07:00
Brian Vaughn
a2c79f2d9e Fixed hydration for events meta data 2019-06-18 10:50:19 -07:00
Brian Vaughn
cf19916be7 Tweaked overflow check 2019-06-18 08:59:27 -07:00
Brian Vaughn
46def793de Merge branch 'when-render-hidden' of https://github.com/justingrant/react-devtools-experimental into justingrant-when-render-hidden 2019-06-18 08:52:08 -07:00
Brian Vaughn
3988c27d70 Merge pull request #325 from bvaughn/hydration
Lazily send props/state/hooks across the bridge
2019-06-18 08:50:21 -07:00
Brian Vaughn
6298fd4248 Hardened the hooks dehydration check 2019-06-18 08:47:37 -07:00
Brian Vaughn
a56fd4c36d Tidied up. Added comments. Renamed a few things. 2019-06-18 08:40:58 -07:00
Brian Vaughn
8e3cd8ab1e Debounce inspect-element polling 2019-06-18 07:41:30 -07:00
Brian Vaughn
6c03f6abbd Tidied up a bit 2019-06-17 14:49:19 -07:00
Brian Vaughn
717af9f5c3 Updated the hydration test harness to cover a bit more 2019-06-17 14:37:49 -07:00
Brian Vaughn
d3d8a5d8b1 Hooks hydrate/dehydrate 2019-06-17 14:30:34 -07:00
Brian Vaughn
7a94ad4e8a Added props/state/context inspection to KeyValue 2019-06-17 11:30:53 -07:00
Dan Abramov
cd98e63b47 [Fresh] Fall back to Map/Set if Weak equivalents are not available (#15907)
* Fall back to Map/Set if Weak equivalents are not available

* Fix Prettier vs Flow fighting
2019-06-17 16:00:29 +01:00
Dan Abramov
a3c5b1fb8b [Fresh] Rename findHostNodesForHotUpdate to findHostInstancesForHotUpdate (#15904) 2019-06-17 15:06:43 +01:00
Brian Vaughn
a6d3f30f95 Initial support for hydration added to both renderer interfaces. 2019-06-16 17:32:37 -07:00
Sebastian Markbåge
7985bf7d50 Remove outdated test renderer comments (#15898) 2019-06-15 16:09:17 -07:00
Dan Abramov
f0156766dc [Fresh] react-fresh => react-refresh (#15888) 2019-06-15 19:36:46 +01:00
Justin Grant
a15f776708 fix: ensure when-rendered content is never hidden 2019-06-15 09:24:37 -07: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
Andrew Clark
661562fc52 Fix outdated test comments (#15892)
Comments for this unit test are confusing because they refer to an
earlier version of the same test.
2019-06-14 16:51:27 -07:00
Andrew Clark
788da69b74 [Suspense] Fix bad loading state not being delayed (#15891)
Fixes a bug where a bad loading state is initially suspended, but a
subsequent update with the same expiration time causes it to
commit immediately.
2019-06-14 16:10:39 -07:00
Dominic Gannaway
353e0ee474 [Flare] remove stopLocalPropagation option + modify responder ownership (#15889) 2019-06-14 23:11:54 +01:00
Dominic Gannaway
a146c1f9ed [Flare] Refactor of Press to fix various issues (#15878) 2019-06-14 22:52:26 +01:00
Dan Abramov
de7a09c1e0 [Fresh] Make transform resilient to plugin order (#15883)
* Run Fresh tests in two modes: with and without destructuring

Destructuring transform messes up the way we collect signatures for Hooks. This adds failing tests.

* Extract collecting calls to Hooks into a separate visitor

This introduces a bit of a perf penalty but makes our plugin resilient to presence of destructuring transform and their order. Fixes new tests.

* Inline some logic into the call visitor
2019-06-14 14:57:20 +01:00
Andrew Clark
2fe8fd290b [Suspense] Use style.setProperty to set display (#15882)
Follow up to #15861.

Turns out you can't set `!important` using a normal property assignment.
You have to use `style.setProperty`.

Maybe Andrew *should* just learn CSS.

IE9 doesn't support `style.setProperty` so we'll fall back to setting
`display: none` without `important`, like we did before #15861 Our
advice for apps that need to support IE9 will be to avoid using
`!important`. Which seems like good advice in general, but IANACSSE.

Tested on FB and using our Suspense DOM fixture.
2019-06-13 18:17:17 -07:00
Andrew Clark
b4b3a1dc66 Fix fuzz test environment variable 2019-06-13 15:59:35 -07:00
Andrew Clark
e91dd70ba2 Remove disableYielding feature flag (#15654)
Obviated by Batched Mode.
2019-06-13 15:58:40 -07:00
Brian Vaughn
5e8678a0a9 Don't send HTMLElements through the bridge when inspecting componetns 2019-06-13 09:09:31 -07:00
Brian Vaughn
9eb6d3465d Updated React version check to account for older (<15) versions 2019-06-12 18:56:39 -07:00
Brian Vaughn
96f7646a1a Updated hydration logic to handle custom objects 2019-06-12 15:43:15 -07:00
Brian Vaughn
cb10c3d6da Lintfix 2019-06-12 15:17:29 -07:00
Brian Vaughn
f6ec82553d Support toggling Suspense from within owners list 2019-06-12 15:13:51 -07:00
Brian Vaughn
f0a29984f4 Merge pull request #320 from gaearon/own
Fix owner tree for legacy backend
2019-06-12 09:58:17 -07:00
Dan
4bfabbc32b Fix owner tree for legacy backend 2019-06-12 17:56:25 +01:00
Brian Vaughn
2e40cc4b18 Merge pull request #319 from gaearon/legacy-fix
Fix some legacy backend bugs
2019-06-12 09:36:20 -07:00
Dan
fdf753021e Distinguish functions and classes 2019-06-12 17:23:29 +01:00
Dan
3137553f6d State and context are on the public instance 2019-06-12 16:50:15 +01:00
Dan
f352fe2625 Maintain rootID for lazily crawled trees 2019-06-12 16:38:35 +01:00
Dan
b5850fe304 Ignore SSR mounts 2019-06-12 16:15:58 +01:00
Timothy Yung
4d949d7641 [React Native] Replace touch discrepancy errors to warnings (#15866) 2019-06-12 11:37:41 +01:00
Dominic Gannaway
45acbdc0ba [Flare] Unsure root events are removed on contextmenu (#15862) 2019-06-12 02:19:02 +01:00
Andrew Clark
198ed661c5 [Suspense] Use !important to hide Suspended nodes (#15861)
Suspended nodes are hidden using an inline `display: none` style. We do
this instead of removing the nodes from the DOM so that their state is
preserved when they are shown again.

Inline styles have the greatest specificity, but they are superseded by
`!important`. To prevent an external style from overriding React's, this
commit changes the hidden style to `display: none !important`.

MaYBE AnDREw sHOulD JusT LEArn Css

I attempted to write a unit test using `getComputedStyle` but JSDOM
doesn't respect `!important`. I think our existing tests are sufficient
but if we were to decide we need something more robust, I would set up
an e2e test.
2019-06-11 11:40:06 -07:00
Dan Abramov
191920605f [Fresh] Implement missing features (#15860)
* Fix existing test

This test included a change in variable name. It wasn't needed, and distracts from the actual thing being tested (the annotation).

* Reset state on edits to initial state argument

* Add a way to check whether there are hot updates

prepareUpdate() now returns null if there are none.

* Add a way to query host nodes for families
2019-06-11 19:37:42 +01:00
Brian Vaughn
6c8ae706ee Merge pull request #316 from gaearon/lighter
Make children selection lighter
2019-06-11 07:13:01 -07:00
Dan Abramov
3bca6b28cd Make children selection lighter 2019-06-10 20:10:24 -06:00
Brian Vaughn
a08e9279ec Merge pull request #315 from bvaughn/settings
Settings panel inlined
2019-06-10 15:44:23 -07:00
Brian Vaughn
dd748ef574 Moved logic to only send updated filters across Bridge to the Store (and added tests) 2019-06-10 15:36:29 -07:00
Brian Vaughn
91e3f6cd4d Removed console.log 2019-06-10 15:05:12 -07:00
Brian Vaughn
e2e598c824 Remember last preferences tab via local storage 2019-06-10 15:03:05 -07:00
Brian Vaughn
19ed98d0c2 Removed Settings panel in favor of new shared Settings modal 2019-06-10 14:57:26 -07:00
Brian Vaughn
402a68d816 Fixed minor border bug in Profiling tab toolbar 2019-06-10 11:14:27 -07:00
Dominic Gannaway
c403ae4d35 [Flare] Move Press root event removal till click phase (#15854) 2019-06-10 19:08:53 +01:00
Dominic Gannaway
f4cd7a38d2 [Flare] Listen to document.body + add stopPropagation to Press (#15853) 2019-06-10 16:51:26 +01:00
Brian Vaughn
37c331533d Merge pull request #173 from bvaughn/legacy
Support legacy React versions
2019-06-09 16:24:00 -07:00
Brian Vaughn
e66fcaf17d Nit 2019-06-09 16:22:23 -07:00
Brian Vaughn
8f53235017 Fixed regression fixtures 2019-06-09 16:16:06 -07:00
Brian Vaughn
80bf1ba0eb Merge branch 'master' into legacy 2019-06-09 16:00:12 -07:00
Brian Vaughn
ea03ddd583 Added Flow type coverage for all EventEmitter subclasses 2019-06-09 15:50:17 -07:00
Brian Vaughn
b3046c6e19 Merge pull request #310 from bvaughn/track-changed-props
Add profiling option to track why a component rendered
2019-06-08 17:45:46 -07:00
Brian Vaughn
3904d634bb Added an explicit 'did not render' label 2019-06-08 17:36:17 -07:00
Brian Vaughn
341d1574cb Tweaked a few inline comments 2019-06-08 17:30:11 -07:00
Brian Vaughn
9047f371e2 Fix minor toolbar border misalignment 2019-06-08 17:18:05 -07:00
Brian Vaughn
4f92af17ea Only show "rendered at" if selected Fiber committed at least once 2019-06-08 17:17:56 -07:00
Brian Vaughn
7a72ee5ac0 Added context changes to sidebar; fixed a initial-mount detection bug 2019-06-08 17:01:38 -07:00
Brian Vaughn
5672d686dc Fixed some minor CSS issues 2019-06-08 16:45:38 -07:00
Brian Vaughn
6ab522326d Added a test for added/removed props 2019-06-08 11:41:39 -07:00
Brian Vaughn
a2f469d742 Fixed an increment bug in sidebar for fiber-commits 2019-06-08 09:22:30 -07:00
Brian Vaughn
2d48401346 Added context support to change description 2019-06-08 09:10:54 -07:00
Dan Abramov
fdc5ca4ba6 Remove dead code 2019-06-07 18:42:12 -07:00
Dan Abramov
90fa0adc0a Fix lint 2019-06-07 18:37:24 -07:00
Dan Abramov
65ac53bba4 Fixes 2019-06-07 18:33:03 -07:00
Dan Abramov
ad7458bb42 Merge branch 'master' into legacy 2019-06-07 17:54:54 -07:00
Dan Abramov
9243bc194c Rewrite to make it sturdier 2019-06-07 17:21:30 -07:00
Brian Vaughn
bd5c2e4621 Initial change tracking implemented
* User profiling setting
* Background collects changed props/state (not added/removed or hooks yet)
* Tests updated
2019-06-07 15:38:26 -07:00
Brian Vaughn
88e59277e7 Added HOC badges to Jest Store serialization 2019-06-07 14:10:49 -07:00
Brian Vaughn
21bb66a8c7 Added HOC filter test 2019-06-07 14:06:08 -07:00
Brian Vaughn
956935f915 Merge pull request #308 from bvaughn/dependabot/npm_and_yarn/js-yaml-3.13.1
Bump js-yaml from 3.12.1 to 3.13.1
2019-06-07 13:15:10 -07:00
dependabot[bot]
c2c3e8e6e5 Bump js-yaml from 3.12.1 to 3.13.1
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.12.1 to 3.13.1.
- [Release notes](https://github.com/nodeca/js-yaml/releases)
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.12.1...3.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2019-06-07 20:12:54 +00:00
Brian Vaughn
78721bde4c Backend notifies the frontend of Storage API support. Frontend disables e.g. reload-and-profile based on this. 2019-06-07 13:08:49 -07:00
Brian Vaughn
3e3c83aecd Updated reload-and-profile temp key to use sessioStorage instead of localStorage 2019-06-07 12:40:59 -07:00
Brian Vaughn
89e36e3976 Wrap all calls to localStorage/sessionStorage to avoid potential runtime errors 2019-06-07 10:51:01 -07:00
Dominic Gannaway
425473f43f [Flare] Improve runtime performance of hit target intersection (#15836) 2019-06-07 15:57:10 +01:00
Dan Abramov
def56c9797 [Fresh] Capture Hook signatures lazily on first render (#15832)
* Split the signature call into two calls

This adds a render-time signature call by making __signature__ curried. We need both calls. The init time tells us which type has which signature. The render time call says when's a good time to capture the lazy Hooks tree. This is necessary for supporting inline requires. I will do that in next commit.

* Lazily compute Hook list on first render

This ensures inline requires don't break comparisons between Hook signatures of previous and next versions by caching Hook list at the time of first render.

* Refactor computing Hook signature keys

Instead of a traversal during the comparison, explicitly compute full keys. This makes it easier to debug mismatches.
2019-06-06 10:53:12 -07:00
Brian Vaughn
a987206a36 Fixed an overflow bug. Added mode-specific CSS style for Firefox. 2019-06-06 10:39:07 -07:00
Dominic Gannaway
8cfcfe0fcb [Flare] Fix ES6 issues with IE11 (#15834) 2019-06-06 18:38:46 +01:00
Dan Abramov
d0e041aee8 [Fresh] Support classes by force-remounting them on edit (#15801)
* Remount classes during hot reload

* Fix a crash when Hook isn't in scope inside the signature

* Minor tweaks

* Support a comment annotation to force state reset

* Refactoring: pass a function instead of WeakMap

This hides the implementation a little bit and reduces how much React knows about the underlying mechanism.

* Refactor: use forceReset to remount unknown Hooks

We already have the logic to reset a component, so let's just reuse it instead of that special case.
2019-06-05 16:13:42 -07:00
Brian Vaughn
d1a88ffc5c Re-add plugin-transform-react-jsx-source plugin for tests 2019-06-05 14:36:01 -07:00
Brian Vaughn
dc9b0810f9 Changed react-window alias 2019-06-05 14:33:24 -07:00
Brian Vaughn
9d90189ee3 react-window sync flushes scroll updates 2019-06-05 14:30:43 -07:00
Brian Vaughn
6ff733873c Vendored react-window 2019-06-05 14:27:57 -07:00
Dominic Gannaway
73c27d8b49 [Flare] Add basic Scroll event responder module (#15827) 2019-06-05 18:20:34 +01:00
Dominic Gannaway
c72dceffbc [Flare] Small Swipe/Drag fixes (#15825) 2019-06-05 17:51:41 +01:00
Christoph Nakazawa
6aaa43708d Rename ReactFeatureFlags to remove the .fb suffix. (#15826) 2019-06-05 14:20:09 +01:00
Ricky
843a59ab60 [React Native] Remove eventTypes from ReactNativeBridgeEventPlugin (#15802) 2019-06-05 13:21:12 +01:00
Andrew Clark
7b28ad119e [Flare] EventPriority enum (#15823)
* Same as previous commit, but for Flare

I don't know what the public API for setting the event priority should
be. Right now it accepts a numeric enum, but is this what we want?
Maybe it should be a string enum? I've punted on this for now.

* Add test for hover events
2019-06-04 17:20:06 -07:00
Brian Vaughn
7ef5970b2f Removed __source info from production builds 2019-06-04 17:03:13 -07:00
Sunil Pai
d707a75794 nit: a quick copy edit for an act() message/comment (#15805) 2019-06-04 16:36:07 -07:00
Dominic Gannaway
cfb79ee5b3 [Flare] Fix isTouchEvent (#15824) 2019-06-04 23:58:11 +01:00
Brian Vaughn
1afc83e7cd Tweaked manifest "version_name" logic 2019-06-04 14:56:36 -07:00
Sarhan Aissi
e158768b16 fix: remove version_name from Firefox WebExtension manifest 2019-06-04 22:34:20 +01:00
Brian Vaughn
7ed3f6815c Merge pull request #295 from bvaughn/horizontal-compression
Components tree changes to improve HOCs and browsing deep trees
2019-06-04 13:59:22 -07:00
Andrew Clark
6b5deeed50 [Events] Add support for events that are both user-blocking and continuous (#15811)
* [Events] Add EventPriority enum

React DOM's DispatchConfig for synthetic events has an `isDiscrete`
field that affects how updates triggered by an event are scheduled.
Events are either discrete or continuous.

This commit adds an additional type of configuration where an event
has user-blocking priority, but is not discrete. E.g. updates triggered
by hover are more important than the default, but they don't need to
be processed serially. Because there are now three types of event
priority instead of two, I've replaced the `isDiscrete` boolean with an
enum: `eventPriority`.

This commit implements the new enum value but does not change any
behavior. I'll enable it behind a feature flag in the next commit.

I've only implemented this in the legacy event system. I'll leave Flare
for a follow-up.

* enableUserBlockingEvents feature flag

Adds a feature flag to increase the priority of events like `mouseover`,
without making them discrete.
2019-06-04 13:35:52 -07:00
Brian Vaughn
7fa5a716e3 Use Circle CI API v2 to get artifacts job ID (#15821) 2019-06-04 13:28:41 -07:00
Dominic Gannaway
8d4fb132ef [Flare] Fix nativeEvent.x/y for older browsers (#15820) 2019-06-04 20:58:20 +01:00
Dominic Gannaway
2534c0c924 [Flare] Add event position properties to Hover responder (#15819) 2019-06-04 18:10:15 +01:00
Brian Vaughn
2245206c4c Add source location to debug logging info 2019-06-04 08:56:10 -07:00
Brian Vaughn
5963998fbe Display density preference updates :root fontSize
As a result, paddings and sizes (e.g. tab bar heights) will also be impacted now by this preference. More importantly, Profile charts will also use the line height preference, so the 'comfortable' setting will hopefully make profiling data easier to read.
2019-06-04 07:24:14 -07:00
Brian Vaughn
b63a41d38a Updated release script to be Workflow aware (#15809) 2019-06-03 17:29:06 -07:00
Nicolas Gallagher
dd43cb5fb9 [Flare] Fix isPressWithinResponderRegion logic (#15808)
Compare the viewport-relative coordinates of getBoundingClientRect with those
of the event's client{X,Y} values. This fixes press within scrollable nodes.
2019-06-03 14:59:26 -07:00
Nicolas Gallagher
4f6cab547b [Flare] Ignore keyboard interactions on text input children (#15810) 2019-06-03 14:34:08 -07:00
Brian Vaughn
95a99867f7 Decreased contrast of HOC badges in selected props panel 2019-06-03 12:51:04 -07:00
Brian Vaughn
ef139a1811 Batched tweaks and bug fixes:
1. Bugfix: Hide tree grouping/background coloring when inside of collapsed subtree.
2. Bugfix: Don't measure and udpate indentation when Components tab is hidden.
3. Tweak: Lower background color for selected subtree in light theme to increase contrast for text.
4. Tweak: Remove FB-specific displayName check/hack since we will address that by modifying the internal require JS transform.
2019-06-03 12:47:26 -07:00
Simen Bekkhus
fa1e8df116 chore: use jest-serializer-raw for react-fresh snapshots (#15806) 2019-06-03 12:46:33 -07:00
Brian Vaughn
edfc1bb2b3 Simplified background highlight style now that corner radius has been removed from selected highlight 2019-06-03 10:46:37 -07:00
Brian Vaughn
06b004b5d4 Renamed <Guideline> to <SelectedTreeHighlight> 2019-06-03 09:39:31 -07:00
Brian Vaughn
fbc6e5d68a Removed outdated comment and Eslint rule ignore 2019-06-03 09:33:48 -07:00
Brian Vaughn
6ac558df2d Reset max indentation when entering/exiting the owner tree 2019-06-03 09:32:28 -07:00
Brian Vaughn
a173f4eb85 Add HOC component filter 2019-06-03 08:51:50 -07:00
Brian Vaughn
78cf211286 Only shrink indentation. Don't increase it again. This avoids 'jumping'. 2019-06-03 08:01:48 -07:00
James Ide
07da821bfd [react-native] Rewrite Haste imports in RN shims and add .fb.js extension (#15786)
This commit is a follow-up to https://github.com/facebook/react/pull/15604, which explains more of the rationale behind moving React Native to path-based imports and the work needed in the React repository. In that linked PR, the generated renderers were updated but not the shims; this commit updates the shims.

The problem is that FB needs a different copy of the built renderers than the OSS versions so we need a way for FB code to import different modules than in OSS. This was previously done with Haste, but with the removal of Haste from RN, we need another mechanism. Talking with cpojer, we are using a `.fb.js` extension that Metro can be configured to prioritize over `.js`.

This commit generates FB's renderers with the `.fb.js` extension and OSS renderers with just `.js`. This way, FB can internally configure Metro to use the `.fb.js` implementations and OSS will use the `.js` ones, letting us swap out which implementation gets bundled.

Test Plan: Generated the renderers and shims with `yarn build` and then verified that the generated shims don't contain any Haste-style imports. Copied the renderers and shims into RN manually and launched the RNTester app to verify it loads end-to-end. Added `.fb.js` to the extensions in `metro.config.js` and verified that the FB-specific bundles loaded.
2019-06-03 15:58:31 +01:00
Brian Vaughn
f713265a00 Cap indentation increase at a max 2019-06-02 21:01:24 -07:00
Brian Vaughn
8261a3f453 Removed Tree padding 2019-06-02 20:25:57 -07:00
Brian Vaughn
dc08e80037 Cache list rows by Element ID rather than index
This is important since we are caching element sizes by DOM (in a WeakMap). Toggling (as well as insertion/deletion) might otherwise break this in some cases.
2019-06-02 20:10:30 -07:00
Jordan Rome
a383c46788 [ESLint] don't warn for Flow type variables (#15804)
In Exhaustive Deps check for react-hooks don't warn if the dependency is
a Flow type variable.
2019-06-03 02:20:51 +01:00
Brian Vaughn
6b6e571c68 Added HOC badge to owners list dropdown 2019-06-02 10:50:07 -07:00
Brian Vaughn
27d4f0b24d Fixed box drawing chars comment 2019-06-02 10:40:10 -07:00
Brian Vaughn
dc945f6b81 Fixed a typo in string truncation util 2019-06-02 10:06:05 -07:00
Brian Vaughn
17b04c321c Cleaned up how we measure children and adjust indentation size 2019-06-02 10:02:22 -07:00
Brian Vaughn
3f0606f3d9 Refactored badges to share code and show +count 2019-06-01 18:48:24 -07:00
Brian Vaughn
6a69a6e991 Added HOC badge to owners stack breadcrumbs 2019-06-01 18:05:59 -07:00
Brian Vaughn
c1989448f4 Disable guide/group highlight in owners tree mode 2019-06-01 17:49:51 -07:00
Brian Vaughn
96dc003a70 Removed debounce+animation from indentation adjustment 2019-06-01 17:48:01 -07:00
Brian Vaughn
b5f8998859 Added debounce and animation for resize 2019-06-01 11:16:18 -07:00
Brian Vaughn
de9fb0a8a2 Tweaked guideline background color style 2019-06-01 09:34:39 -07:00
Brian Vaughn
ab7ae78511 Tweaked a few styles 2019-06-01 09:19:32 -07:00
Brian Vaughn
2845a7883b Whoops I broke CI (updating snapshots) 2019-06-01 08:44:55 -07:00
Brian Vaughn
aa87b125e7 Lots of tweaks
Remove selected guideline in favor of background color for selected subtree.
Add badges in grid format to selected elements prop panel.
Show badges beside owners list.
2019-06-01 08:24:24 -07:00
Andrew Clark
5763f1d4c4 [Events] Nested discrete events across systems
If an event in the old system is dispatched synchronously within an
event from the new system, or vice versa, and the inner event is a
discrete update, React should not flush pending discrete updates before
firing the inner event's handlers, even if the outer event is not
discrete.

Another way of saying this is that nested events should never force
React to flush discrete updates.

Arguably, if the outer event is not a discrete event, then the inner
event _should_ flush the pending events. However, that would be a
breaking change. I would argue this isn't so bad, however, given that
nested events are pretty rare. They don't fit nicely into our event
model regardless, since we don't support nested React renders. In the
future we should consider warning when events are nested.
2019-05-31 17:46:30 -07:00
Andrew Clark
7aa35ceae0 Fix casing of shouldflushDiscreteUpdates
shouldflushDiscreteUpdates -> shouldFlushDiscreteUpdates
2019-05-31 17:46:30 -07:00
Andrew Clark
91635dd483 Switch to "discrete" and "continuous" terminology
Events were previously described as "interactive" or "non-interactive".
2019-05-31 17:46:30 -07:00
Andrew Clark
73c380fca7 WorkPhase -> ExecutionContext
WorkPhase is an enum that represents the currently executing phase of
the React update -> render -> commit cycle. However, in practice, it's
hard to use because different "phases" can be nested inside each other.
For example, the commit phase can be nested inside the
"batched phase."

This replaces WorkPhase with a different concept: ExecutionContext.
ExecutionContext is a bitmask instead of an enum. It represents a stack
of React entry points. For example, when `batchedUpdates` is called
from inside an effect, the ExecutionContext is
`BatchedContext | CommitContext`.
2019-05-31 17:46:30 -07:00
Nicolas Gallagher
88b3963820 [Flare] Remove deprecated keypress event (#15795)
`keypress` is a deprecated event.
2019-05-31 14:53:09 -07:00
Brian Vaughn
19d95a1368 Revert "Re-added indent lines"
This reverts commit 33432b037f.
2019-05-31 14:41:20 -07:00
Mateusz Burzyński
63fe08eef5 React Events: allow Tab+Alt on Mac in Focus responder (#15679)
* Fix issue with Tab+alt not being considered as isGlobalFocusVisible candidate on Mac
* Add test for Tab+alt on Mac setting pointerType: "keyboard" on a focus event
2019-05-31 14:33:42 -07:00
Brian Vaughn
33432b037f Re-added indent lines 2019-05-31 13:34:55 -07:00
Brian Vaughn
5a269e7ced Initial POC for compressing horizontal offset for wide/deep trees 2019-05-31 11:24:34 -07:00
Dan Abramov
2794b92164 Add some support for reordering 2019-05-31 18:00:56 +01:00
Dan Abramov
c3be085910 Remove crawling for updates
It doesn't seem necessary to crawl because mounts only happen in the context of updates.

This fixes updates to not be treated as new mounts.
2019-05-31 17:41:11 +01:00
Dan Abramov
6fd83acb1d Default to showing host nodes for legacy renderer 2019-05-31 15:39:00 +01:00
Dan Abramov
9f44251ebf Remove unnecessary code for host text as we skip it anyway 2019-05-31 14:27:22 +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
Brian Vaughn
c0f686eed9 Show indent lines preference 2019-05-30 14:30:17 -07:00
Brian Vaughn
a2a468743f Remove hover guideline in favor of showing guidelines for every nesting level 2019-05-30 14:17:12 -07:00
Brian Vaughn
a957031fe7 Fixed bad Bridge disconnections 2019-05-30 09:27:28 -07:00
Brian Vaughn
8f8ac358c6 Turn off pointer events for guidelines 2019-05-30 08:43:45 -07:00
Brian Vaughn
ec421355bd Added selected and hovered guidelines to Components tree 2019-05-30 08:22:06 -07:00
Andrew Clark
3b2302253f Fix sizebot (#15771)
The previous naming scheme used the name of the resulting bundle file.
However, there are cases where multiple bundles have the same filename.
This meant whichever bundle finishes last overwrites the previous ones
with the same name.

The updated naming scheme is `bundle-sizes-<CI_NODE_INDEX>.json`.
Instead of generating a separate info file per bundle, it now creates
one per process.
2019-05-29 21:30:16 -07:00
Nicolas Gallagher
0f7cc2ba84 React Events: check window before using navigator (#15768) 2019-05-29 20:19:31 -07:00
Andrew Clark
ad9a6df58c Move fixtures test to its own CI job
Running it in parallel to the other post-build jobs shaves ~30 seconds
off the total CI time.
2019-05-29 15:11:25 -07:00
Nicolas Gallagher
2670bc3400 React Events: support legacy browser Spacebar key value (#15766) 2019-05-29 15:00:43 -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
Andrew Clark
8ce8b9ab81 Update name of CI job in sizebot (#15767)
Same as #15714. I moved the artifacts step to a different job, so I
need to update the name in the sizebot script to match.
2019-05-29 14:52:11 -07:00
Andrew Clark
1cc3bba004 Parallelizes the build script across multiple processes (#15716)
* Write size info to separate file per bundle

`bundle-sizes.json` contains the combined size information for every
build. This makes it easier to store and process, but it prevents us
from parallelizing the build script, because each process would need to
write to the same file.

So I've updated the Rollup script to output individual files per build.
A downstream CI job consolidates them into a single file.

I have not parallelized the Rollup script yet. I'll do that next.

* Parallelize the build script

Uses CircleCI's `parallelism` config option to spin up multiple build
processes.
2019-05-29 14:34:50 -07:00
Brian Vaughn
d5be489d5b Backed out Bridge shutdown refactor as it seems to have introduced bugs 2019-05-29 14:23:10 -07:00
Andrew Clark
30b1a8009c Don't extract errors in CI (#15758)
Removes `--extract-errors` argument from CI build script command.
Instead, the author is expected to run `yarn extract-errors` locally
or manually edit the error code map.

The lint rule should be sufficient to catch unminified errors, but
as an extra precaution, I added a post-build step that greps the
production bundles. The post-build step works even if someone disables
the lint rule for a specific line or file.
2019-05-29 14:20:29 -07:00
Andrew Clark
112168f31b Lint rule for unminified errors (#15757)
* Lint rule for unminified errors

Add a lint rule that fails if an invariant message is not part of the
error code map.

The goal is to be more disciplined about adding and modifiying
production error codes. Error codes should be consistent across releases
even if their wording changes, for continuity in logs.

Currently, error codes are added to the error code map via an automated
script that runs right before release. The problem with this approach is
that if someone modifies an error message in the source, but neglects to
modify the corresponding message in the error code map, then the message
will be assigned a new error code, instead of reusing the existing one.

Because the error extraction script only runs before a release, people
rarely modify the error code map in practice. By moving the extraction
step to the PR stage, it forces the author to consider whether the
message should be assigned a new error code. It also allows the reviewer
to review the changes.

The trade off is that it requires more effort and context to land new
error messages, or to modify existing ones, particular for new
contributors who are not familiar with our processes.

Since we already expect users to lint their code, I would argue the
additional burden is marginal. Even if they forget to run the lint
command locally, they will get quick feedback from the CI lint job,
which typically finishes within 2-3 minutes.

* Add unreleased error messages to map
2019-05-29 11:29:04 -07:00
Dominic Gannaway
142cf56cbf [Flare] Adds onContextMenu and fixes some contextmenu related issues (#15761) 2019-05-29 17:53:55 +01:00
Dan Abramov
556cc6fe19 [Fresh] Generate signatures for Hooks (#15733)
* Generate signatures for Hooks

This currently only works one level deep. For custom Hooks, we'll need to add some way to compose signatures.

* Be more resilient to plugin conflicts

This prevents a class of problems where other plugins cause our visitor to re-run.

It's a standard Babel practice, e.g.:

8c7d4b55c9/packages/babel-plugin-transform-react-constant-elements/src/index.js (L85-L86)

* Remove unnecessary stuff from debugging

* Include Foo.useHookName() calls into the signature

* Add an integration test for adding/removing an effect

* Add integration test for changing custom Hook order

* Include custom Hooks into the signatures

* Fix inferred names for function expressions

* Support export default hoc(Foo) when Foo is defined separately

* Add more built-in Hooks
2019-05-29 14:15:31 +01:00
Sebastian Markbåge
b74fa9868e Clean up (#15755)
expirationTime has already been checked if it's sync.

timeout can now be longer than 5 seconds when a suspense config is used.
We might want to adjust the heuristics but it's not internally consistent
without this.
2019-05-28 14:19:51 -07:00
Brian Vaughn
5429f651b4 Tweaks 2019-05-28 13:57:05 -07:00
Sunil Pai
388b03dd12 prettier 2019-05-28 20:24:35 +01:00
Sunil Pai
9e87e654f5 pass tests and flow 2019-05-28 20:21:55 +01:00
Sunil Pai
c7580fcd3f Merge remote-tracking branch 'upstream/master' into act-async 2019-05-28 20:21:38 +01:00
Andrew Clark
d915a4c1f1 [Suspense] Add Batched Mode variant to fuzz tester (#15734) 2019-05-28 11:41:01 -07:00
Owen Conti
7c5645ddb1 Fix double spaces. (#15641) 2019-05-28 10:34:18 -07:00
Brian Vaughn
92c2d8366b Updated Chrome installation
1. Removed auto-updates XML (since the feature doens't work for self hosted extensions)
2. Replaced CRX with packed ZIP (since people are having trouble with the CRX, and auto-udpates doesn't work anyway)
2019-05-28 08:52:21 -07:00
Caleb Meredith
401065fe5c Adds test for #15732. (#15747) 2019-05-28 14:25:22 +01:00
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
Brian Vaughn
fa0139afbf Merged master 2019-05-26 10:47:55 -07:00
Brian Vaughn
af47c39dbb Added and view-source support for Memo components 2019-05-26 10:33:19 -07:00
Brian Vaughn
4422337562 Added another (disabled) test; refactored getChildren slightly 2019-05-26 08:37:05 -07:00
Brian Vaughn
94bebda825 Merged master 2019-05-25 09:10:43 -07: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
Brian Vaughn
bda8a0aa98 Decreased contrast of disabled button icons to look more obviously disabled 2019-05-24 16:00:12 -07:00
Brian Vaughn
c8411019f1 Updated profiler overview 2019-05-24 14:43:56 -07:00
Brian Vaughn
e76cee394d Added section about inspecting element to OVERVIEW 2019-05-24 14:31:05 -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
Brian Vaughn
4cc7e748d1 Merge pull request #289 from bvaughn/cache-inspected-element
Cache inspected element data until it is updated
2019-05-24 09:26:31 -07:00
Brian Vaughn
efc2f82da2 Reorganize inspected element state vars slightly 2019-05-24 09:17:20 -07:00
Brian Vaughn
f580d0ece7 Don't (re)serialize inspected elements either unless they have re-rendered since last inspected. 2019-05-24 09:07:15 -07:00
Brian Vaughn
07db37f030 Cache inspected element data until it is updated 2019-05-24 07:37:46 -07:00
Andrew Clark
2b58797365 Typo in CircleCI config 2019-05-23 15:33:56 -07:00
Brian Vaughn
408fbee23b Fix potential RTE caused by setting (saved) profiling data while profiling is in progress 2019-05-23 14:49:47 -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
Brian Vaughn
395c02567c Handle HTTPS Git clone URLs 2019-05-23 11:55:32 -07:00
Brian Vaughn
6e8c2015fc Tweaked Bridge shutdown sequence slightly 2019-05-23 11:46:28 -07:00
Brian Vaughn
34f6fa4fab Added a sanity test for Bridge shutdown 2019-05-23 11:22:02 -07:00
Brian Vaughn
f47b40fe6c Tweaked event display name logic 2019-05-23 09:30:31 -07:00
Dominic Gannaway
9a67ba2f98 Remove snapshot 2019-05-23 09:17:50 -07:00
Dominic Gannaway
70084e881b Update snapshot tests 2019-05-23 09:17:37 -07:00
Dominic Gannaway
8eb7eddd1f Run prettier 2019-05-23 09:17:37 -07:00
Dominic Gannaway
779fd167ff Adds inspectable event components + props
[Flare] Adds inspectable event components + props
2019-05-23 09:17:37 -07:00
Brian Vaughn
e4aa3c5b33 Update profiling-supported status each time roots change (and added tests) 2019-05-23 09:09:35 -07:00
Brian Vaughn
74d8207e06 Improved visual style of Profiling-disabled button 2019-05-23 08:52:27 -07:00
Brian Vaughn
541dd6c4b6 Moved profiling-supported subscription into ProfilerContext 2019-05-23 08:48:51 -07:00
Brian Vaughn
0608b1a554 Merge pull request #281 from bvaughn/persiste-profiling-data-after-navigation
[WIP] Don't erase profiler data on navigation
2019-05-23 08:38:59 -07:00
Brian Vaughn
44fbf3cd1d Added ProfilerContext tests 2019-05-23 08:36:34 -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
Brian Vaughn
5719454377 Persist profiling data after navigation 2019-05-22 20:00:21 -07:00
Brian Vaughn
351d5f662a Add Tab id to Tooltip 2019-05-22 20:00:06 -07:00
Brian Vaughn
f14a2fd05c Use @reach tooltips for TabBar, cleanup supports-profiling subscription 2019-05-22 18:44:43 -07:00
Dominic Gannaway
b962adfc2b [Flare] event component displayName is now mandatory (#15717) 2019-05-23 01:29:07 +01:00
Brian Vaughn
98623dfdb0 Tweak 2019-05-22 16:40:40 -07:00
Dominic Gannaway
d98161874c [Flare] Ensure DOM inspection is Flare compatible 2019-05-22 16:29:54 -07: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
Brian Vaughn
eaaeb439b4 Fixed a missing remove-event-listener in ProfilerStore 2019-05-22 10:52:15 -07:00
Brian Vaughn
b556f7444d Profiler properly handles unmounted roots 2019-05-22 10:19:26 -07:00
Brian Vaughn
b4a3ef9fb2 Merge pull request #279 from bvaughn/profiling-architecture-eager-data-push
Refactor Profiler architecture
2019-05-22 10:00:52 -07:00
Brian Vaughn
962865e5bf Add datetime to the profiling export filename 2019-05-22 09:57:10 -07:00
Brian Vaughn
fbd82385d2 Fixed a state cleanup issue if Profiler data is cleared 2019-05-22 09:04:55 -07:00
Brian Vaughn
d1344768b2 Changed export code to (hopefully) support larger exports 2019-05-22 08:41:57 -07:00
Brian Vaughn
ec44eb1e4c Tweaked did-not-render text color to be slightly dimmer 2019-05-22 08:32:10 -07:00
Brian Vaughn
a03c3b5d14 Bumped Profiler exported data version 2019-05-22 08:22:33 -07:00
Brian Vaughn
d09299bf85 Cleaned up some tests 2019-05-22 08:05:34 -07:00
Brian Vaughn
99b6a44beb Updated event subscriptions and getters to use new ProfilerStore 2019-05-22 07:40:41 -07:00
Brian Vaughn
2d4bb01c01 Moved profiling data to ProfilerContext to fix re-import bug 2019-05-22 07:28:26 -07:00
Brian Vaughn
95bd6c8f63 Added export to web shell and removed 'downloads' API permission 2019-05-22 06:46:42 -07:00
Brian Vaughn
36d51f4eb6 Added root selector UI to Profiler 2019-05-22 06:40:04 -07:00
Brian Vaughn
c6de014a9a Massively overhauled profiling data architecture 2019-05-22 06:05:25 -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
7ce9f4859c Renamed Store importedProfilingData -> profilingData 2019-05-20 10:45:16 -07:00
Brian Vaughn
f1561e9e17 Merge pull request #274 from bvaughn/commit-priority-level
Show commit priority levels in Profiler UI (if available)
2019-05-20 09:56:58 -07:00
Brian Vaughn
d440380719 Upgraded to canary with priority level info 2019-05-20 09:54:07 -07:00
Brian Vaughn
53de5b69cc Updated test snapshot 2019-05-20 09:42:37 -07:00
Brian Vaughn
16a81feb72 Moved priority level constants into rendeer interface 2019-05-20 09:39:26 -07:00
Brian Vaughn
9a6a19456f Show commit priority levels in Profiler UI 2019-05-20 09:39:26 -07: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
Brian Vaughn
146fd2ad3d Fixed snapshot diff 2019-05-17 07:54:07 -07:00
Brian Vaughn
629e500fe2 Merge pull request #275 from lucasecdb/fix/undefined-chartnode
Fix undefined chart node when switching commits in profiler
2019-05-17 07:52:07 -07:00
Lucas Cordeiro
1e025edb9a Fix undefined chart node when switching commits in profiler 2019-05-17 09:35:10 -03: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
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
Brian Vaughn
b6c135c165 Added Jest tests for OwnersListContext 2019-05-09 14:21:22 -07:00
Brian Vaughn
564a223368 Fetch owners list from renderer (using suspense)
Owners in the list may have been filtered out of the Store, but in the owners list view- it's important to still show them. The frontend cannot do this on its own, so this list needs to come from the renderer interface.
2019-05-09 11:47:22 -07:00
Dominic Gannaway
3d8b836e22 Event API: ensure we pop context for event system fibers (#15599) 2019-05-09 17:01:18 +01:00
Dominic Gannaway
e33e32db04 Event API: normalize event timeStamp property to be in event system (#15598) 2019-05-09 16:05:25 +01:00
Dominic Gannaway
3669b90101 Event API: add more warnings for responder based events (#15597) 2019-05-09 15:31:18 +01:00
Brian Vaughn
17516b76ae Dim owners that have been filtered from the tree in rendered-by list 2019-05-08 18:23:54 -07:00
Brian Vaughn
0722a5a024 Tweaked REAMDE 2019-05-08 17:58:31 -07:00
Brian Vaughn
ee099124e2 Fixed a Profiler memoization bug and improved test coverage 2019-05-08 15:41:57 -07:00
Brian Vaughn
d42f86bb50 Updated Profiling chart tests to cover components with duration=0 2019-05-08 14:35:43 -07:00
Brian Vaughn
df10afba51 Merge pull request #262 from submetu/enhancement/label-improvement
Profiler: Improve labels for times that round to 0.0ms
2019-05-08 14:26:16 -07:00
Brian Vaughn
4f1d347c04 Custom filters are applied by default after extension reload 2019-05-08 14:22:06 -07:00
Subhan
34a38dc4f0 updates snapshots and removes extra formatting from formatTime 2019-05-08 23:33:26 +03:00
Subhan
d3522f1f66 Uses FormDuration and FormTime to format times that are 0 into something more readable 2019-05-08 23:18:43 +03:00
Brian Vaughn
98260f8614 Added installation instructions to README 2019-05-08 12:53:22 -07:00
Dominic Gannaway
05d08500b2 Experimental Event API: Press event properties (#15586) 2019-05-08 20:29:03 +01:00
Dominic Gannaway
51e66cf9fa Experimental Event API: reduce code size of event modules (#15590) 2019-05-08 19:09:32 +01:00
Dominic Gannaway
8abf243b86 Ensure touch events are properly handled for pageX and pageY (#15587) 2019-05-08 19:08:15 +01:00
Brian Vaughn
703706b40f Add toggle-suspense button to all elements
This button is disabled if the renderer returns canToggleSuspense=false.
2019-05-08 10:50:32 -07:00
Brian Vaughn
dbe68f7a67 Updated lint ignore for new dev shell dist folder 2019-05-08 08:52:48 -07:00
Subhan
60511aadc0 Profiler: Improve labels for times that round to 0.0ms 2019-05-08 10:11:52 +03:00
Sebastian Markbåge
c7398f3396 Add Suspense Boundary Context (and unstable_avoidThisFallback) (#15578)
* Avoidable suspense boundaries

* Move the context out of SuspenseComponent

* Use setDefaultShallowSuspenseContext instead of passing 0
2019-05-07 18:08:05 -07:00
Andrew Clark
f9e60c8a19 Warn when suspending at wrong priority (#15492)
* Warn when suspending at wrong priority

Adds a warning when a user-blocking update is suspended.

Ideally, all we would need to do is check the current priority level.
But we currently have no rigorous way to distinguish work that was
scheduled at user- blocking priority from work that expired a bit and
was "upgraded" to a higher priority. That's because we don't schedule
separate callbacks for every level, only the highest priority level per
root. The priority of subsequent levels is inferred from the expiration
time, but this is an imprecise heuristic.

However, we do store the last discrete pending update per root. So we
can reliably compare to that one. (If we broaden this warning to include
high pri updates that aren't discrete, then this won't be sufficient.)

My rationale is that it's better for this warning to have false
negatives than false positives.

Potential follow-ups:
- Bikeshed more on the message. I don't like what I landed on that much
but I think it's good enough to start.
- Include the names of the components that updated. (The ideal place to
fire the warning is during the setState call but we don't know if
something will suspend until the next update. Maybe we could be clever
and warn during a subsequent update to the same component?)

* Move Suspense priority check to throwException
2019-05-07 16:50:04 -07:00
Brian Vaughn
a54581c2dd Fixed invalid DOM nesting warning 2019-05-07 15:25:17 -07:00
Brian Vaughn
44e90e6ef4 Upgrade @reach UI and remove tooltip fork 2019-05-07 15:22:57 -07:00
Brian Vaughn
97b7fdd2d9 Fixed a deprecated prop warning from react-window 2019-05-07 14:47:37 -07:00
Brian Vaughn
278661715c Show import error dialog if profiling data import fails 2019-05-07 14:38:11 -07:00
Brian Vaughn
acdc9bae67 Added export+import profiling data test coverage
Also fixed an incomplete import feature as well as a regression in export that had gone unnoticed due to previous lack of test coverage.
2019-05-07 13:08:46 -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
Brian Vaughn
90701815b6 Merge pull request #258 from bvaughn/profiler-test-experiments
Added profiler tests
2019-05-06 14:00:45 -07:00
Brian Vaughn
7ead699714 Prettier 2019-05-06 13:58:49 -07:00
Brian Vaughn
6ab8972345 Update to React canary release for interaction tracing bugfix 2019-05-06 13:52:27 -07:00
Brian Vaughn
c2bf71f406 Added commit tree builder test 2019-05-06 13:41:36 -07:00
Brian Vaughn
b25d996fc4 Added profiling chart data tests 2019-05-06 13:37:06 -07:00
Brian Vaughn
d86bc1020e Hardened tests to ensure expectations are flushed 2019-05-06 13:04:14 -07:00
Brian Vaughn
6da04b5d88 Fix interaction tracing for batched update mounts (#15567)
* Added failing test for act+interaction tracing
* Mark pending interactions on root for legacy unbatched phase
2019-05-06 12:59:48 -07:00
Dominic Gannaway
d38cfd452f Ensure TouchHitTarget element is server side rendered with hit slop (#15385)
* Follow up to 15381

* Add back in hit slop properties

* Prettier

* Fix lint

* move hydration update out of DEV block

* Remove pointer-events:auto
2019-05-06 20:13:23 +01:00
Brian Vaughn
705cd9b109 Added Flow types to profiling test 2019-05-06 09:44:01 -07:00
Brian Vaughn
c29483122c Removed outdated TODO comment 2019-05-05 09:56:54 -07:00
Brian Vaughn
269969b645 Updated snapshot data after ReactDOM batch fix 2019-05-05 09:52:27 -07:00
Brian Vaughn
1c49a7ef59 Added remaining profiling tests. One currently fails because of a bug with act() and interaction tracing 2019-05-04 14:22:50 -07:00
Brian Vaughn
da1e5776b1 Added a second Profiling test (for CommitDetails) and fixed some module reset prolems 2019-05-04 13:11:56 -07:00
Brian Vaughn
dd96b3314c Cleaned up tests a bit. Profiling test uses mock timers now. 2019-05-04 09:36:13 -07:00
Nicolas Gallagher
2e5d1a8b9e React Events: fix cancel events for Press (#15563)
* Fixes a bug in the cancellation logic. The cancel events are now correctly listened to on the root.
* Fixes cancellation in Safari by using the dragstart event as a proxy for cancellation (i.e., the event dispatched when move-during-press occurs on an anchor tag)
2019-05-03 15:33:21 -07:00
Brian Vaughn
f7c8e3a05c Experimenting with profiler tests 2019-05-03 15:01:26 -07:00
Brian Vaughn
a8ed95445c Store profiler snapshot data by root (and clear on root unmount) 2019-05-03 14:59:20 -07:00
Nicolas Gallagher
307e0a7d7d React Events: cancel onLongPress for large enough moves (#15562)
Implements the behaviour from React Native's Pressability.
2019-05-03 12:59:55 -07:00
Dominic Gannaway
339366c461 Event API: Support press reentry for pointer events (#15560) 2019-05-03 18:32:50 +01:00
Brian Vaughn
a552b7b5f7 Only clear Profiling snapshot on root-unmount 2019-05-03 10:12:45 -07:00
Brian Vaughn
73cf0fa32b Merge branch 'master' into sompylasar-232-clear-profiling-data-for-unmounted-root 2019-05-03 10:01:43 -07:00
Brian Vaughn
542409954a Merge pull request #257 from bvaughn/right-align-flame-graph
Right-align flame graph children
2019-05-03 10:01:23 -07:00
Brian Vaughn
8585ee37db Renamed assertOneMap -> assertEmptyMap 2019-05-03 09:30:48 -07:00
Brian Vaughn
8850a9a64a Merge branch '232-clear-profiling-data-for-unmounted-root' of https://github.com/sompylasar/react-devtools-experimental into sompylasar-232-clear-profiling-data-for-unmounted-root 2019-05-03 09:24:58 -07:00
Brian Vaughn
e71bda5257 Right-align flame graph children 2019-05-03 09:21:26 -07:00
Brian Vaughn
435e22ad1b Fixed deploy script 2019-05-03 08:55:31 -07:00
Brian Vaughn
07281993d1 Merge pull request #242 from sompylasar/improve-flow-coverage-any
Improve Flow coverage by reducing typecasts through `any`
2019-05-03 08:00:47 -07:00
Brian Vaughn
868cf67aa4 Removed findCurrentFiberUsingSlowPath() in favor of findCurrentFiberUsingSlowPathById() 2019-05-03 07:56:24 -07:00
Brian Vaughn
7f4482e438 Removed optional_chaining from Flow config 2019-05-03 07:48:30 -07:00
Brian Vaughn
40ed0ca839 Merge branch '165-add-flow-types-for-fiber' of https://github.com/sompylasar/react-devtools-experimental into sompylasar-165-add-flow-types-for-fiber 2019-05-03 07:48:21 -07:00
Brian Vaughn
4bf3ac1910 Fixed broken path-selection after filter changes 2019-05-02 15:21:29 -07:00
Brian Vaughn
d7447a8458 Fixed bug in Store.getIndexOfElementID() that caused roots with multiple top-level children to return an incorrect item index 2019-05-02 15:12:57 -07:00
Brian Vaughn
4e04907d13 Added badge for enabled filter count 2019-05-02 10:53:40 -07:00
Brian Vaughn
ef596be1ef Merge pull request #207 from sompylasar/131-highlight-all-children
Support highlighting of all DOM elements of Fragments, not just first
2019-05-02 08:31:22 -07:00
Brian Vaughn
1473e9efc8 Merge pull request #245 from bvaughn/custom-filtering
Add configurable component filters
2019-05-01 17:52:27 -07:00
Brian Vaughn
83b521c7b4 Updated Flamechart to support multiple nodes at root 2019-05-01 17:44:38 -07:00
Brian Vaughn
4a4786ac2f Misc cleanup 2019-05-01 14:18:20 -07:00
Brian Vaughn
e6da4b9058 Renamed FilterType -> ComponentFilterType 2019-05-01 14:01:03 -07:00
Brian Vaughn
e45deb5471 Removed $FlowFixMe comments 2019-05-01 13:59:54 -07:00
Brian Vaughn
540207901d Added some component filtering tests 2019-05-01 13:31:55 -07:00
Brian Vaughn
8429220164 Added filter UI (but with a lot of $FlowFixMe comments) 2019-05-01 10:45:18 -07:00
Brian Vaughn
0b4bfbc98f Add support for hide-by-name and hide-by-path component filter regexps 2019-05-01 10:45:18 -07:00
Brian Vaughn
a2ba90bf96 Fixed a path selection bug when filter pereferences are updated 2019-05-01 10:45:18 -07:00
Brian Vaughn
c4c51c0821 Prevent filter preference changes while profiling is active 2019-05-01 10:45:18 -07:00
Brian Vaughn
eb9705abc8 Removed FilterList UI for now (collapsed into Settings component) 2019-05-01 10:45:18 -07:00
Brian Vaughn
a241780dc2 Filter changes are applied to the renderer without reloading 2019-05-01 10:45:18 -07:00
Brian Vaughn
27a1820039 Refactored filter preferences a bit more to be stored in the Store 2019-05-01 10:45:18 -07:00
Brian Vaughn
ee1b38e4db Added filter preference types and plugged into renderer partly. Lots of work to do still. 2019-05-01 10:45:18 -07:00
Brian Vaughn
9db209ee64 Initial pass at adding filter-by-type Flow types and support to renderer 2019-05-01 10:45:18 -07:00
Brian Vaughn
17c5feb66a Reorganized types shared between backend and frontend slightly. 2019-05-01 10:45:18 -07:00
Brian Vaughn
18b34b4926 Rearranged Settings UI in prep for custom filter controls 2019-05-01 10:45:18 -07:00
Brian Vaughn
a9aa9f2106 Merge pull request #251 from gaearon/devserver
Use WebpackDevServer for local testing
2019-05-01 09:29:43 -07:00
Dan Abramov
b9ae9393b9 Use WebpackDevServer for local testing 2019-05-01 17:19:26 +01:00
Ivan Babak
cd89c0d75f Clear profiling data for root when the root is unmounted
Fixes https://github.com/bvaughn/react-devtools-experimental/issues/232
2019-05-01 01:46:47 -07:00
Ivan Babak
c6c71ef8f9 Fix profiling screenshots data structure to map rootID to commitIndex
Propagate `rootID` throughout the code for `captureScreenshot`.

Rename private profiling maps of `store` to make relations more clear.

Fix missing cleanup for screenshots data in `set importedProfilingData` of `store`.
2019-05-01 01:07:36 -07:00
Ivan Babak
d1f6e762e4 Improve Flow coverage by reducing typecasts through any
There are many unnecessary typecasts through `any` which
break the Flow of types across the program.

It's more bulletproof to avoid lying to ourselves about types.

Also fixed sketchy null check where zero ID would be skipped:
```diff
-  } else if (selectedElementID) {
+  } else if (selectedElementID !== null) {
```
2019-05-01 00:31:13 -07:00
Dominic Gannaway
ec6691a687 Event API: remove isTargetDirectlyWithinEventComponent (#15546) 2019-04-30 17:38:48 +01:00
Brian Vaughn
abcb613223 Minor Bridge code tweaks:
1. Renamed a variable
2. Coerced undefined to null
3. Added a couple of console.warn() for unexpected paths
2019-04-30 09:23:11 -07:00
Brian Vaughn
5204ae87bc Merge pull request #229 from sompylasar/217-workaround-disconnected-port-error
Fix for 'Attempting to use a disconnected port object'
2019-04-30 09:15:52 -07:00
Brian Vaughn
b24216a7b1 Merge pull request #234 from gaearon/nested-suspense-test
Add test coverage for nested Suspense
2019-04-30 08:51:58 -07:00
Brian Vaughn
9e1b1e8c91 Merge pull request #233 from gaearon/preset-env
Start using @babel/preset-env
2019-04-30 08:50:17 -07:00
Brian Vaughn
da951ec9bb Merge pull request #243 from sompylasar/rename-profiler-types-to-frontend-backend-to-disambiguate
Rename Profiler types to disambiguate which is Frontend and Backend
2019-04-30 08:47:05 -07:00
Brian Vaughn
44205f16d9 Merge pull request #247 from sompylasar/fix-flow-on-circleci
Fix Flow failure on CircleCI due to the number of workers
2019-04-30 08:32:37 -07:00
Dominic Gannaway
a6e30001fb Delete duplicate Focus.js (#15540)
This file was renamed to the lower case version, but as Mac filesystems are typically case insensitive, it was never removed.
2019-04-30 12:20:44 +01:00
Dominic Gannaway
f7993d5477 Delete duplicate Hover.js (#15539)
This file was renamed to the lower case version, but as Mac filesystems are typically case insensitive, it was never removed.
2019-04-30 12:13:07 +01:00
Dominic Gannaway
c8ee10037a Delete duplicate Swipe.js (#15541)
This file was renamed to the lower case version, but as Mac filesystems are typically case insensitive, it was never removed.
2019-04-30 12:11:26 +01:00
Dominic Gannaway
494716c9b4 Delete duplicate Drag.js (#15537)
This file was renamed to the lower case version, but as Mac filesystems are typically case insensitive, it was never removed.
2019-04-30 12:07:24 +01:00
Dominic Gannaway
377846fef8 Delete duplicate Press.js (#15538)
This file was renamed to the lower case version, but as Mac filesystems are typically case insensitive, it was never removed.
2019-04-30 12:06:44 +01:00
Dominic Gannaway
379515e83e Follow up to 15535 (#15536) 2019-04-30 12:04:19 +01:00
Dominic Gannaway
bd88982fbf Event API: use capture for all event listeners using experimental responder system (#15526) 2019-04-30 11:40:45 +01:00
Ivan Babak
bfbde71657 Fix Flow failure on CircleCI due to the number of workers
https://github.com/flowtype/flow-bin/issues/138#issuecomment-448416874
https://github.com/flowtype/flow-bin/issues/138#issuecomment-450367472

> This will stop flow from trying to consume too many virtual CPUs (which CircleCI doesn't actually provide), letting it run to completion without first running out of memory and killing its sub processes.

The log output in CircleCI was:
https://circleci.com/gh/bvaughn/react-devtools-experimental/201
```
#!/bin/bash -eo pipefail
yarn flow
yarn run v1.10.1
$ /home/circleci/repo/node_modules/.bin/flow
Launching Flow server for /home/circleci/repo
Spawned flow server (pid=259)
Logs will go to /tmp/flow/zShomezScirclecizSrepo.log
Monitor logs will go to /tmp/flow/zShomezScirclecizSrepo.monitor_log
Launching Flow server for /home/circleci/repo
Spawned flow server (pid=361)
Logs will go to /tmp/flow/zShomezScirclecizSrepo.log
Monitor logs will go to /tmp/flow/zShomezScirclecizSrepo.monitor_log
Launching Flow server for /home/circleci/repo
Spawned flow server (pid=464)
Logs will go to /tmp/flow/zShomezScirclecizSrepo.log
Monitor logs will go to /tmp/flow/zShomezScirclecizSrepo.monitor_log
Launching Flow server for /home/circleci/repo
Spawned flow server (pid=567)
Logs will go to /tmp/flow/zShomezScirclecizSrepo.log
Monitor logs will go to /tmp/flow/zShomezScirclecizSrepo.monitor_log
Lost connection to the flow server (0 retries remaining): -Out of retries, exiting!
error Command failed with exit code 7.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Exited with code 1
```
2019-04-29 21:56:53 -07:00
Andrew Clark
72ca3c60e7 Bump scheduler version to 0.14.0 (#15395) 2019-04-29 18:10:11 -07:00
Andrew Clark
7882c41f60 Use lowercase entry points for event modules (#15535)
Matches npm convention
2019-04-29 16:25:56 -07:00
Nathan Schloss
43c4e5f348 Add method for forcing a lower framerate 2019-04-29 15:51:58 -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
Eli White
12e5a13cf2 [React Native] Inline calls to FabricUIManager in shared code (#15490)
* [React Native] Inline calls to FabricUIManager in shared code

* Call global.nativeFabricUIManager directly as short term fix

* Add flow types

* Add nativeFabricUIManager global to eslint config

* Adding eslint global to bundle validation script
2019-04-29 14:31:16 -07:00
Nicolas Gallagher
2cca18728e React Events: add onFocusVisibleChange to Focus (#15516)
Called when focus visibility changes. Focus is only considered visible if a
focus event occurs after keyboard navigation. This provides a way for people to
provide visual focus styles for keyboard accessible UIs without those styles
appearing if focus is triggered by mouse, touch, pen.
2019-04-29 13:52:15 -07:00
Ivan Babak
d35cf80921 Remove Fiber type properties we don't use in DevTools 2019-04-28 12:57:28 -07:00
Dan Abramov
d351b46aee Merge pull request #238 from sompylasar/fix-typo-recursivelyinitializetree
Fix typo `recursivelyIniitliazeTree` -> `recursivelyInitializeTree`
2019-04-28 13:38:49 +01:00
Dan Abramov
7c04883f8d Merge pull request #239 from sompylasar/remove-agent-addbridge
Remove Agent addBridge: there can only be one bridge, add in constructor
2019-04-28 13:38:34 +01:00
Ivan Babak
1b5f043e01 Fix for 'Attempting to use a disconnected port object'
Fixes https://github.com/bvaughn/react-devtools-experimental/issues/217

The error reproduces with any two React websites, e.g. `https://reactjs.org` and `https://nextjs.org`, by keeping the DevTools Components tab open and switching between these websites in the same browser tab.

There are several issues with the code that contribute to this:
1. `Bridge` leaves behind a dangling timer that fires `_flush` after the bridge has been abandoned ("shutdown").
2. `bridge.send('shutdown')` is asynchronous, so the event handlers do not get unsubscribed in time.
3. `port.onDisconnect` does not trigger on in-tab navigation like new URL or back/forward navigation.
4. State management design of the code that uses shared variables and callbacks makes it hard to handle race conditions originating from the browser.

This commit cleans up some of the lacking symmetry when using `addListener`/`removeListener`, but the code in `shells/browser/shared/src/main.js` is hard to reason about with regards to race conditions, and there are many possible race conditions originating from the browser, so maybe there could be a better design paradigm (like a formal state machine) to manage the state changes in response to sequences of events than plain old event listeners, callbacks, and shared variables.

Unrelated, but clicking Chrome Back/Forward/Back/Forward very fast makes the browser and the DevTools and the DevTools of DevTools stall and become unresponsive for some time, then recovers but the Back/Forward/Stop/Refresh button and favicon loading indicator may remain broken. Looks like a Chrome bug, some kind of a temporary deadlock in handling the browser history.
2019-04-28 04:45:57 -07:00
Ivan Babak
d3e5fcd81c Rename Profiler types to disambiguate which is Frontend and Backend
Flow IDE shows the original type, not the file-scoped alias,
so it's confusing to see incompatible variables that have types
with the same name.

This started from `src/devtools/ProfilingCache.js` where
`ProfilingSummary` was incompatible, but I decided to make a bigger
change for consistency and to avoid similar mistakes in the future.
2019-04-28 04:40:39 -07:00
Ivan Babak
9f06bc345f Add Flow types for Fiber
Fixes https://github.com/bvaughn/react-devtools-experimental/issues/165
2019-04-28 04:18:27 -07:00
Ivan Babak
0b817777b4 Remove Agent addBridge: there can only be one bridge, add in constructor
Let's make impossible states truly impossible, and fix Flow types, too.

All three usages of Agent called addBridge right after constructing it.
Agent has one field `_bridge` which is force-typed as not-null despite
there's a temporary zone between the constructor end and addBridge start
where `_bridge` is null.
2019-04-28 04:03:28 -07:00
Ivan Babak
19bfba7943 Fix typo recursivelyIniitliazeTree -> recursivelyInitializeTree 2019-04-28 03:52:33 -07:00
Nicolas Gallagher
cc5a49379b React Events: FocusScope tweaks and docs (#15515)
* FocusScope: rename trap to contain.
* FocusScope: avoid potential for el.focus() errors.
* FocusScope: add docs.
* Update docs formatting.
2019-04-26 13:38:01 -07:00
Dominic Gannaway
796c67a25f Event API: responder event types should not re-register on EventComponent update (#15514) 2019-04-26 21:33:54 +01:00
Dan Abramov
d81d74b236 Add test coverage for nested Suspense 2019-04-26 20:04:28 +01:00
Dan Abramov
e5ed266873 Start using @babel/preset-env 2019-04-26 19:37:23 +01:00
Dan Abramov
2118b1fe1b Merge pull request #230 from gaearon/assert-maps
Assert empty maps when there are no roots
2019-04-26 18:15:04 +01:00
Dan Abramov
b6a55989f5 Assert empty maps when there are no roots 2019-04-26 17:47:00 +01:00
Brian Vaughn
c28acc5d47 Changed owners back button label to say 'Up to <...>' 2019-04-26 09:38:25 -07:00
Dominic Gannaway
c4d1dcb533 React Events: core API documentation followup (#15506) 2019-04-26 15:47:28 +01:00
Dan Nate
41ef1961c1 Update TopLevelEventTypes.js (#15511)
Fix grammar of code comment.
2019-04-26 14:58:32 +02:00
Dominic Gannaway
7a482af5d8 Event API: Fix bug where Press root events were not being cleared (#15507) 2019-04-26 10:30:38 +01:00
Ivan Babak
281616f462 Support highlighting of all DOM elements of Fragments, not just first
Fixes https://github.com/bvaughn/react-devtools-experimental/issues/131

Uses the new function `findAllCurrentHostFibers`.

Removes dependency on React's `renderer.findHostInstanceByFiber` function
which used to highlight only the first DOM element of a Fragment.

Reworked `src/backend/views/Overlay` to support highlighting
more than one element rectangle annotated with one tooltip.
Fixed minor issues with the tooltip position calculation.
2019-04-26 01:22:49 -07:00
Nicolas Gallagher
a14e24efab React Events: core API documentation (#15505) 2019-04-26 08:11:40 +01:00
Dominic Gannaway
8658611b6c Event API: ensure event keys are unique + add validation (#15501) 2019-04-26 08:00:57 +01:00
Brian Vaughn
707b44834f Merge pull request #213 from wldcordeiro/fix-firefox-perms
fix: correct permissions for Firefox
2019-04-25 19:11:39 -07:00
Nicolas Gallagher
d9839740ef React events: remove unused types (#15503) 2019-04-25 15:11:53 -07:00
Brian Vaughn
043b73e0a8 Merge pull request #223 from bvaughn/owners-list-intermediate-components
Owners list view should drill through intermediate components
2019-04-25 15:10:08 -07:00
Brian Vaughn
09029acf00 Refactored owners list to use cached metadata (and added more tests) 2019-04-25 15:06:24 -07:00
Brian Vaughn
15eacae02c Moved owners list calculations into the store and added tests
This is being done to fix a drill-through bug, although the initial fix is perhaps not the most performant one. At least we have test coverage now and a temporary fix.
2019-04-25 15:06:24 -07:00
Brian Vaughn
b6d617ac7f Added 'back to owner' button when owners stack is collapsed 2019-04-25 15:05:39 -07:00
Brian Vaughn
e88819a22e Reverse direction of menu items within drop-down owners list 2019-04-25 14:10:51 -07:00
Nicolas Gallagher
0b34311705 React events: fix press end event dispatching (#15500)
This patch fixes an issue related to determining whether the end event occurs
within the responder region. Previously we only checked if the event target was
within the responder region for moves, otherwise we checked if the target was
within the event component. Since the dimensions of the child element can
change after activation, we need to recalculate the responder region before
deactivation as well if the target is not within the event component.
2019-04-25 13:00:22 -07:00
Dominic Gannaway
d1f667acc0 Event API: follow up fixes for FocusScope + context changes (#15496) 2019-04-25 20:10:33 +01:00
Dan Abramov
a0b1fb37fb Merge pull request #227 from gaearon/string-table
Transfer strings in a string table
2019-04-25 17:54:11 +01:00
Dan Abramov
1bea469db0 Remove unneeded variable 2019-04-25 17:46:48 +01:00
Dan Abramov
af2d1374c4 Let -> const 2019-04-25 17:39:13 +01:00
Dan Abramov
3920ebd0a1 Clarify encoding in overview 2019-04-25 17:32:46 +01:00
Dan Abramov
c8f8943c9a Transfer strings in a string table 2019-04-25 17:11:24 +01:00
Kunuk Nykjær
c530639dd2 Minor code structure adjustments to the bundles.js file (#15079)
* simplify

* fix error

* use deepFreeze

* move comments
2019-04-25 16:24:01 +01:00
Dan Abramov
c1363b7e17 Merge pull request #226 from gaearon/mutate-children
Improve performance by mutating the children array
2019-04-25 15:27:36 +01:00
Dan Abramov
2e423c21b0 Merge pull request #221 from gaearon/heuristic
Use a heuristic for locating roots
2019-04-25 15:22:34 +01:00
Dan Abramov
e1383c666d Allow to set tracked path multiple times
Fixes #225. This happens when you close and reopen DevTools while on the same page.
2019-04-25 14:57:39 +01:00
Dan Abramov
2993b168e5 Mutate the children array 2019-04-25 14:47:05 +01:00
Dan Abramov
d5319566a1 Fix broken start:prod command 2019-04-25 14:21:58 +01:00
Alec Larson
ed36df46c6 add --watch mode to "yarn build" (#15116)
* wip: add --watch mode to "yarn build"

* fix: handle error events
2019-04-25 12:55:44 +01:00
Redmond Tran
793ef9b855 test(eslint-plugin-react-hooks): add coverage for unused custom hook (#15130) 2019-04-25 12:15:29 +01:00
Jeffrey Berry
d61da93878 test(accumulate): add test suite for accumulate function (#15159)
* refactor(typo): remove typo 'be'

* test(accumulate): add test suite for accumulate function
2019-04-25 12:12:25 +01:00
Adam Comella
a187e9b5e4 React Native: Allow Views to be nested inside of Text (#15464)
This feature is now supported on both iOS and Android. The Android feature was merged a couple of weeks ago: https://github.com/facebook/react-native/pull/23195.
2019-04-25 12:06:39 +01:00
Radu-Sebastian Amarie
f85aadefc0 ADD: disablePictureInPicture attribute for HTML5 videos (#15334)
* ADD: disablePictureInPicture attribute for HTML5 videos

* ADD: disablePictureInPicture as DOMProperty and attribute

* Update: Replace camelCase with lowercase and vice-versa

* FIX: Missing comma on attribute (prettier)
2019-04-25 12:02:27 +01:00
FUJI Goro
1eb2b892df give canUseDOM with a possibility to be a constant (#14194)
https://webpack.js.org/plugins/define-plugin/

Webpack's DefinePlugin has the ability to replace `typeof expr` to a constant in compile-time, which should lead to better dead-code-elimination.
2019-04-25 11:28:53 +01:00
shubham
de26d6dd36 typo fix (#15493)
changed ReactResponderContext.dispatchEvent otpions keys to options.
2019-04-25 09:37:35 +01:00
Dominic Gannaway
64e3da286f Event API: Add FocusScope surface (#15487) 2019-04-25 02:01:09 +01:00
Dan Abramov
80597a2377 Use a heuristic for locating roots 2019-04-24 23:02:41 +01:00
Dan Abramov
942f67c936 Merge pull request #220 from gaearon/removed-ids
Select parent node if selection is removed
2019-04-24 19:25:05 +01:00
Dominic Gannaway
3f058debc2 Event API: various bug fixes (#15485) 2019-04-24 17:56:21 +01:00
Brian Vaughn
7bae48f00c Fixed minor CSS overflow issue 2019-04-24 09:07:53 -07:00
Brian Vaughn
c855a862c3 Merge pull request #218 from gaearon/bump-react
Bump React versions
2019-04-24 08:45:16 -07:00
Dan Abramov
949384f4ca Select parent node if selection is removed 2019-04-24 16:29:23 +01:00
Dan Abramov
52deada495 Bump React versions 2019-04-24 15:57:43 +01:00
Dan Abramov
54aecf487e Merge pull request #215 from bvaughn/persist-selection
Try to restore selection between reloads
2019-04-24 15:50:29 +01:00
Dan Abramov
f123763fe1 Read index off the Fiber 2019-04-24 15:05:33 +01:00
Dan Abramov
5d2d4213ec Delete stale paths 2019-04-24 15:05:21 +01:00
Dan Abramov
e050529c7d Read renderer ID from operations 2019-04-24 15:00:46 +01:00
Dan Abramov
26162988aa Fix tests 2019-04-24 14:37:46 +01:00
Dan Abramov
7eb7c5a350 Match Fibers to saved selection as they mount
This implements matching Fibers against the tracked selection path.

The algorithm is optimized to do as little checks as possible:

* When not trying to restore selection, we don't do anything
* When restoring selection, we only check .return pointers of new mounts
* Only when .return pointers match our current deepest match, we compare the frames
2019-04-24 14:37:46 +01:00
Dan Abramov
3bb837b683 Implement getPathForElement to serialize the selected path
Note this doesn't restore the selection yet.
2019-04-24 14:37:46 +01:00
Dan Abramov
b1a7007cc5 Keep track of root insertion order in the renderer
Normally, Fibers have key or index which we'll use to match things up between reloads. However, roots don't have such a concept. We'll use their insertion order as an approximation. If it's consistent, we'll be able to restore the selection.
2019-04-24 14:37:46 +01:00
Dan Abramov
d8abecdcf9 Persist and restore selection in agent
This implements the infrastructure for saving and restoring renderer-specific selection state in the session storage.

Note this doesn't actually implement the calculation and tracking of paths in the renderer. It only simulates that the renderer can do it. The actual implementation will come in a later commit.
2019-04-24 14:37:46 +01:00
Brendan McLoughlin
fb28e90482 Add missing word to code comment for clarity (#15443) 2019-04-24 11:03:51 +01:00
Dominic Gannaway
fa2fa3564d Experimental event API: adds context.isTargetDirectlyWithinEventComponent (#15481) 2019-04-24 11:02:47 +01:00
Dominic Gannaway
d3af2f2a5d Experimental Event API: add event component mount phase callback (#15480) 2019-04-24 10:41:24 +01:00
Brian Vaughn
085d00e877 Merge pull request #196 from bvaughn/selected-element-suspense
Convert inspected element (right panel) to use Suspense
2019-04-23 18:33:05 -07:00
Brian Vaughn
7262a30cf3 Reverted optimization to avoid re-sending inspected fiber unless it committed 2019-04-23 18:04:25 -07:00
Andrew Clark
ce126fbb23 Fix priority inference of next level of work (#15478)
Bugfix for `inferPriorityFromExpirationTime` function. It happened to
work in our existing tests because we use virtual time.

Flow would have caught this if expiration times were an opaque type. We
should consider that in the future. (The downside of opaque types is
that all operations would have to go through helper functions, which may
or may not get inlined by Closure.)
2019-04-23 16:41:05 -07:00
Andrew Clark
71c8759ceb Measure callback timeout relative to current time (#15479)
Fixes a bug where the timeout passed to `scheduleCallback` represented
an absolute timestamp, instead of the amount of time until that
timestamp is reached. The solution is to subtract the current time
from the expiration.

The bug wasn't caught by other tests because we use virtual times that
default to 0, and most tests don't advance time.

I also moved the `initialTimeMs` offset to the
`SchedulerWithReactIntegration` module so that we don't have to remember
to subtract the offset every time. (We should consider upstreaming this
to the Scheduler package.)
2019-04-23 16:40:55 -07:00
Andrew Clark
9c6ff136c7 Remove timeout from performance flamegraph (#15477)
The implementation is wrong, but also it's not that useful for
debugging. Implementing it properly would involve tracking more
information than we do currently. Perhaps including the priority
of the callback in the message would be helpful, but not sure. For now
I'll just remove it.
2019-04-23 15:42:25 -07:00
Dan Abramov
299a2714c3 Use stricter equality check (#15474) 2019-04-23 23:28:02 +01:00
Brian Vaughn
0aa7d2f800 Reverted optimization to avoid re-sending inspected fiber unless it committed 2019-04-23 14:03:58 -07:00
Brian Vaughn
1e5c0b7856 Re-added the selection message 2019-04-23 13:43:38 -07:00
Dominic Gannaway
017d6f14b7 Experimental Event API: add rootEventTypes support to event responders (#15475)
* Adds rootEventTypes
2019-04-23 19:55:50 +01:00
Brian Vaughn
4dcb34ea32 Fixed Flow error 2019-04-23 11:32:07 -07:00
Brian Vaughn
53c7338420 Updated flow-bin to attempt to fix the error 2019-04-23 09:00:25 -07:00
Brian Vaughn
d85f566d66 Merged master (tooltip changes) 2019-04-23 08:49:40 -07:00
Brian Vaughn
8b33dd673d Added @reach/tooltip 2019-04-23 08:41:52 -07:00
Dominic Gannaway
784ebd8fa9 Experimental event API: rework the propagation system for event components (#15462) 2019-04-23 11:50:48 +01:00
Brian Vaughn
ec7536704d Locked down canary versions 2019-04-22 19:32:16 -07:00
Brian Vaughn
7f1531044b Differentiate between no-change and no-element-found when inspecting element 2019-04-22 15:37:55 -07:00
Brian Vaughn
00872e2e51 Fixed suspense fallback issue by moving inspection message side effect before suspending render 2019-04-22 15:25:55 -07:00
Brian Vaughn
64bb2d31f9 Fixed bug with cache invalidation 2019-04-22 15:18:32 -07:00
Brian Vaughn
64bc49d523 Run first setState with explicit priority in case of non-React event handlers 2019-04-22 15:11:04 -07:00
Wellington Cordeiro
2d8c28733d fix: correct permissions for Firefox
remove the `background` permissions as it's not used by Firefox, but `activeTab` is and we needed
it.

fix #136
2019-04-22 15:12:33 -06:00
Brian Vaughn
e31ae91023 Removed duplicate scheduler module 2019-04-22 13:10:47 -07:00
Brian Vaughn
ba640df982 Merge branch 'master' into selected-element-suspense 2019-04-22 10:47:34 -07:00
Brian Vaughn
433934f55e Refactored TreeContext to use less memoization (based on feedback from Sebastian) 2019-04-22 10:39:21 -07:00
Brian Vaughn
d53ae2ea8a Refactored TreeContext to use less memoization (based on feedback from Sebastian) 2019-04-22 10:19:59 -07:00
Brian Vaughn
70be637d48 Don't schedule an update with React unless the curent element was invalidated 2019-04-22 09:37:55 -07:00
Brian Vaughn
5970bf4b40 Changed polling approach. Fixed remove event typo. 2019-04-22 09:37:55 -07:00
Brian Vaughn
3de18de25e Tried to implement two setState pattern, but it does not feel right 2019-04-22 09:37:55 -07:00
Brian Vaughn
957c389566 Adding polling and initial stab at not serializing duplicate inspected Element props 2019-04-22 09:37:34 -07:00
Brian Vaughn
c6b19cc141 Refactored insepected element cache to use the context API 2019-04-22 09:37:34 -07:00
Brian Vaughn
09b023a6e6 Naive suspense implementation for selected element panel
This commit leaves a few major things uunresolved:
* We aren't yet polling for updates
* We aren't yet using the two setState pattern
* The resource cache will grow unbounded over time because we aren't yet clearing items from it
* The renderer interface is not smart enough to avoid resending unchanged data between requests
2019-04-22 09:37:34 -07:00
Brian Vaughn
76b29ad0a9 Merge pull request #201 from gaearon/scroll-fix
Fix scrolling to selected row in collapsed mode
2019-04-22 09:37:15 -07:00
Nicolas Gallagher
587676900f React events: initial implementation of disabled prop (#15458) 2019-04-21 18:17:18 -07:00
Nicolas Gallagher
59c7aef91d React events: add a test for focusable descendants (#15457) 2019-04-21 17:47:52 -07:00
Nicolas Gallagher
0a8da33916 React events: README update types and remove stopPropagation prop (#15456) 2019-04-21 17:46:07 -07:00
Brian Vaughn
52652f3456 Toggle method no longer emits 'mutated' event unless it mutated the store 2019-04-21 12:20:23 -07:00
Brian Vaughn
129466ed91 Yarn deploy sets production NODE_ENV 2019-04-21 09:05:55 -07:00
Brian Vaughn
a01fc44a78 Merge pull request #205 from bvaughn/@reach/tooltip
[BLOCKED] Use new @reach/tooltip
2019-04-21 09:01:23 -07:00
Brian Vaughn
91f74a5134 Fixed focus styles for OwnersStack dropdown toggle button 2019-04-21 08:59:24 -07:00
Brian Vaughn
09b995ab1c Tidied up CSS variables 2019-04-21 08:38:58 -07:00
Brian Vaughn
66df03d179 Renamed CSS var color-text-color to color-text 2019-04-21 08:29:51 -07:00
Brian Vaughn
8220df734c Tweaked hover and focus colors. Temporarily disabled Tooltip. 2019-04-21 08:23:20 -07:00
Brian Vaughn
a129089891 Tweaking focus/active colors and only showing focus rect on tab 2019-04-20 15:44:24 -07:00
Brian Vaughn
403bf49a78 Use new @reach/tooltip 2019-04-20 14:29:03 -07:00
Brian Vaughn
4218dcbf99 Merge pull request #203 from gaearon/push-ops
Push operations directly to the array
2019-04-20 14:27:53 -07:00
Brian Vaughn
740993baa9 Merge branch 'master' into push-ops 2019-04-20 14:26:46 -07:00
Brian Vaughn
72156c744f Merge pull request #204 from gaearon/no-weakset
Replace WeakSet with return pointer check
2019-04-20 14:23:59 -07:00
Brian Vaughn
94d9f61a7d Merge pull request #206 from gaearon/leading
Ignore leading edge of find-by-DOM throttle
2019-04-20 14:22:49 -07:00
Dan Abramov
006e03c38e Ignore leading edge of find-by-DOM throttle 2019-04-20 22:17:12 +01:00
Dan Abramov
c0d7023a88 Replace WeakSet with return pointer check 2019-04-20 21:42:30 +01:00
Dan Abramov
02a3a22753 Push operations directly to the array 2019-04-20 21:05:52 +01:00
Brian Vaughn
4b9082eea1 Changed style and position of search-for-element button to more closely matchin Chrome ( based on user testing) 2019-04-20 10:44:03 -07:00
Dan Abramov
4ffdffb598 Fix scrolling to selected row in collapsed mode 2019-04-20 16:20:03 +01:00
Brian Vaughn
3697ed2bba Merge pull request #199 from gaearon/another-check
Filter out dehydrated Suspense nodes
2019-04-20 08:00:14 -07:00
Brian Vaughn
da2ed30471 Merge pull request #200 from gaearon/clear-stuff
Clear DOM overlay on shutdown
2019-04-20 07:57:11 -07:00
Dan Abramov
d05106e364 Clear DOM overlay on shutdown 2019-04-20 14:34:13 +01:00
Dan Abramov
a186dc2e8d Filter out dehydrated Suspense nodes 2019-04-20 13:57:33 +01:00
Nicolas Gallagher
d584fcdc6e React events: use passive events where possible (#15454) 2019-04-19 13:09:03 -07:00
Nicolas Gallagher
051513bfa0 React Events: consolidate logic for Press event component (#15451)
Refactor of Press and additional regression coverage.

The logic for "start", "move", "end", and "cancel" events is consolidated into a single block to reduce duplication and improve consistency of the UX across input-types. Also reduces code size.

The bailout logic for anchor tags is removed since we preventDefault for click by default. We can discuss scenarios where it makes sense to limit functionality around interactions on anchor tags.

The logic for ignoring emulated events is simplified and improved. Pointer events can produce emulated touch (immediately after pointer) and mouse events (delayed) which is now accounted for and tested.
2019-04-19 10:05:28 -07:00
Nicolas Gallagher
cdfce1ad23 React events: consolidate logic of Hover event component (#15450)
Minor refactor of Hover and additional regression coverage.
2019-04-19 09:51:36 -07:00
Nicolas Gallagher
5857c89da2 React events: extract common helper functions (#15449) 2019-04-19 08:40:18 -07:00
Brian Vaughn
d7e8fccd1a Fixed an OVERVIEW typo 2019-04-19 07:54:30 -07:00
Brian Vaughn
5b0b9c9fbc Merge pull request #193 from gaearon/no-reorder
Don't reorder a single child
2019-04-19 07:51:51 -07:00
Dan
9a395c2f2c No need to reorder empty children either 2019-04-19 13:21:09 +01:00
Dan
fb8ad3486e Don't reorder a single child 2019-04-19 13:19:58 +01:00
Dan Abramov
2adbfd9607 Merge pull request #186 from gaearon/more-suspensey-stuff
Fix more Suspense issues
2019-04-19 13:18:50 +01:00
Dan
efb5855c8c Nits 2019-04-19 13:17:17 +01:00
Dan
3e657a6031 Prettier 2019-04-19 13:09:25 +01:00
Dan Abramov
37dd1ec8f8 Merge branch 'master' into more-suspensey-stuff 2019-04-19 13:09:01 +01:00
Brian Vaughn
f286c0d901 Increased contrast for selected+inactive background color 2019-04-18 18:19:10 -07:00
Brian Vaughn
c6a27d1fea Merge branch 'master' of github.com:bvaughn/react-devtools-experimental 2019-04-18 18:13:43 -07:00
Brian Vaughn
c0b414d581 Node scripts should fail if not NODE_ENV specified 2019-04-18 18:13:34 -07:00
Brian Vaughn
131e2e52db Merge pull request #188 from gaearon/humble-search
Don't select search result unless user does something
2019-04-18 18:04:28 -07:00
Brian Vaughn
60b614f527 Renamed TREE_OPERATION_RESET_CHILDREN -> TREE_OPERATION_REORDER_CHILDREN 2019-04-18 17:59:53 -07:00
Brian Vaughn
24736e4ff5 Hardened reorder child invariants 2019-04-18 17:58:48 -07:00
Dan Abramov
3d09b4aaa5 Don't select search result unless user does something 2019-04-19 01:54:39 +01:00
Brian Vaughn
21afd6ea20 Merge pull request #184 from bvaughn/harden
Harden assertions
2019-04-18 17:50:17 -07:00
Dan Abramov
b0c0a11f1b Revert accidental change 2019-04-19 01:41:00 +01:00
Dan Abramov
72e67b343f Add Concurrent Mode test 2019-04-19 01:18:25 +01:00
Dan Abramov
534dfb0ca2 Optimize: don't recreate ID arrays all the time 2019-04-19 01:13:25 +01:00
Dan Abramov
8830ba890c Fix more Suspense traversal bugs 2019-04-19 01:09:57 +01:00
Dan Abramov
346b628b43 Add failing tests for Suspense with same type 2019-04-19 00:36:55 +01:00
Dan Abramov
d44bf272ad Refactor: materialize typed array in one place 2019-04-19 00:32:29 +01:00
Dan Abramov
ccecde76d1 Harden assertions 2019-04-19 00:29:49 +01:00
Brian Vaughn
3dfbf8ad6b Added a new invariant to the store (bridge operations handler) 2019-04-18 15:40:50 -07:00
Brian Vaughn
7930bad8c6 Deploy production extension builds 2019-04-18 14:45:24 -07:00
Brian Vaughn
e2aedb2ea7 Merge pull request #181 from gaearon/consoleerror
Fail tests on errors in renderer
2019-04-18 10:08:44 -07:00
Dan Abramov
d0b5e3a7cb Update setupTests.js 2019-04-18 18:06:34 +01:00
Brian Vaughn
d6e829d7a5 Fixed bug in reset-children to properly calculate new root weight 2019-04-18 09:54:26 -07:00
Brian Vaughn
89f7a0c048 Merge pull request #182 from bvaughn/suspense-toggle
Fixed a Suspense toggling bug that incorrectly impacted tree weight
2019-04-18 09:45:22 -07:00
Brian Vaughn
358e63ac3d Fixed a Suspense toggling bug that incorrectly impacted tree weight 2019-04-18 09:38:41 -07:00
Dan Abramov
8c5794eab3 Fail tests on errors in renderer 2019-04-18 17:03:04 +01:00
Brian Vaughn
b45e743f52 Merge pull request #180 from gaearon/suspense-more-fixes
Fix unmounting in Concurrent Mode
2019-04-18 08:52:30 -07:00
Dan Abramov
6a13ffd231 Traverse the previous current tree when switching from primary to fallback 2019-04-18 16:22:50 +01:00
Dan Abramov
24309fde06 Add failing Concurrent Mode stress tests 2019-04-18 16:22:50 +01:00
Dan Abramov
0f44e9fb98 Move sync stress tests in their own file 2019-04-18 16:22:50 +01:00
Brian Vaughn
456e937b83 Merge pull request #178 from gaearon/removal-integrity
Assert removal happens in the right order
2019-04-18 08:16:22 -07:00
Dan Abramov
d02d93712e Assert removal happens in the right order 2019-04-18 16:02:08 +01:00
Brian Vaughn
08279fb342 Merge pull request #174 from robertknight/mousedown-tab-select
Select tab when the mouse is pressed
2019-04-18 08:00:01 -07:00
Brian Vaughn
d995f19339 Merge pull request #175 from lucasecdb/assign-timeout
Assign timeoutID to avoid multiple requests
2019-04-18 07:56:32 -07:00
Lucas Cordeiro
6df050e726 Assign timeoutID to avoid multiple requests 2019-04-18 06:46:06 -03:00
Robert Knight
c2865dbab9 Select tab when the mouse is pressed
Selecting the tab when the mouse is pressed rather than only when it is
released makes tab switching feel faster and also matches how the Chrome dev
tools behave.

The previous tab selection handler which listens for the radio button's
selection has been kept for the benefit of interaction methods which
don't trigger the mousedown handler.
2019-04-18 08:16:52 +01:00
Brian Vaughn
29811cd24e Added legacy (v15) tests 2019-04-17 15:30:20 -07:00
Brian Vaughn
7ab93402a8 Initial support for v15+ via new legaacy renderer 2019-04-17 14:36:15 -07:00
Brian Vaughn
0d932d770b Merge pull request #168 from bvaughn/collapse-nodes-by-default
Configurable tree default collapsed/expanded behavior
2019-04-17 13:29:25 -07:00
Brian Vaughn
75e1e1431b Expanded the reorder tests slightly 2019-04-17 13:11:18 -07:00
Nicolas Gallagher
0b50fb29f7 Include rootEventTypes in DOMEventResponderSystem stopPropagation tests (#15433) 2019-04-17 13:08:36 -07:00
Brian Vaughn
634d4fece2 Added more inline comments 2019-04-17 13:03:18 -07:00
Brian Vaughn
29d43a2230 Merge pull request #171 from bvaughn/improve-contrast-light-mode
Improve contrast for light mode
2019-04-17 11:44:25 -07:00
Brian Vaughn
3fb9f6cdaa Improve contrast for light mode 2019-04-17 11:40:55 -07:00
Nicolas Gallagher
1ae409d2c7 React events: fix nested Hover components error (#15428)
* Add failing test for nested Hover
* Fix error caused by nested Hover event components
2019-04-17 11:33:32 -07:00
Brian Vaughn
c107e03132 Flow fix 2019-04-17 09:45:03 -07:00
Brian Vaughn
74be389124 Fixed a bug with re-ordering of children within a collapsed node 2019-04-17 09:39:54 -07:00
Brian Vaughn
178e89927a Fixed some edge cases with collapsed by default. Still some bugs existing. 2019-04-17 07:45:33 -07:00
Brian Vaughn
037bb0034c Throw if root node is collapsed 2019-04-16 14:10:06 -07:00
Brian Vaughn
4b64d7c017 Support configurable node/tree collapsed by default behavior 2019-04-16 13:59:36 -07:00
Nicolas Gallagher
c73ab39c1f React events: make nested Focus work as expected (#15421)
This patch makes a change to the Focus module so that it only reports
focus/blur on the host node that's a direct child of the event component. This
brings the expected behaviour in line with the browser default of focus/blur
events not bubbling for Pressable.
2019-04-16 11:16:27 -07:00
Dan Abramov
85179fe4a7 Merge pull request #164 from gaearon/fix-lots-of-stuff
Fix reordering and Suspense logic
2019-04-16 19:11:28 +01:00
Dan Abramov
3a6d656090 Remove unnecessary condition 2019-04-16 19:10:39 +01:00
Dan Abramov
9182d0b0aa Bump alpha to get Andrew's fix 2019-04-16 19:09:52 +01:00
Dan Abramov
58bb7cea41 Remove unused lines 2019-04-16 18:21:40 +01:00
Dan Abramov
8576c85b0d Move stress tests to their own file 2019-04-16 18:10:15 +01:00
Dan Abramov
d4db178d33 Bump to canary 2019-04-16 17:39:26 +01:00
Dan Abramov
3cf67ab859 Harden the tests and fix Flow 2019-04-16 17:02:42 +01:00
Dan Abramov
b1dea26251 Fix the remaining issue when primary child is null
This lets us unlock the rest of the Suspense test.
2019-04-16 16:57:10 +01:00
Dan Abramov
fe21ee7ca0 Enable part of Suspense test that was failing before
This PR fixes it.
2019-04-16 16:47:26 +01:00
Dan Abramov
f4e223bceb When resetting Suspense children, use the fallback child set if needed
This fixes the bug I introduced in the previous refactor which Suspense test caught.
2019-04-16 16:45:56 +01:00
Dan Abramov
dd935ea178 Propagate the need to reset children to closest visible Fiber
This fixes the bug.
2019-04-16 16:34:08 +01:00
Dan Abramov
57e8513a30 Refactor: remove early returns from updateFiberRecursively
This doesn't change any logic, just the shape of the control flow.
I want to unify some branches at the end, so it's easier if there are no early returns.
2019-04-16 16:34:08 +01:00
Dan Abramov
f4c3008cf5 Refactor: split recordUpdate() into profiling and reorder
This doesn't change the actual algorithm but splits unrelated parts.
2019-04-16 16:34:08 +01:00
Dan Abramov
b081ffc518 Add stress test for reordering 2019-04-16 16:34:08 +01:00
Brian Vaughn
20193f03c0 Merge pull request #162 from gaearon/suspense-test
Add Suspense stress test
2019-04-16 07:49:11 -07:00
Dan
d89f79d6e6 Add Suspense stress test 2019-04-16 00:14:49 +01:00
Andrew Clark
4221565e15 Cancel pending commit before starting on root
Moves the cancelTimeout call to right before creating a new work-in-
progress root. Fixes a class of bugs where a pending commit is not
cancelled, causing an incomplete tree to accidentally commit.

In the interest of fixing downstream bugs quickly, I'm landing this
without a test case; I'll add one in a follow up.
2019-04-15 16:00:18 -07:00
Brian Vaughn
8c974ae432 Flow and lint fix 2019-04-15 09:43:52 -07:00
Brian Vaughn
97636fa7fc Merge pull request #161 from gaearon/fast
Don't materialize typed array until the transfer
2019-04-15 09:40:33 -07:00
Brian Vaughn
2b3ecc63b3 Merge pull request #158 from gaearon/stress-test
Add a stress test for tree traversal
2019-04-15 09:34:40 -07:00
Dan Abramov
6b9b80faac Don't materialize typed array until the transfer 2019-04-15 16:27:19 +01:00
Brian Vaughn
b3546e0e02 Merge pull request #160 from gaearon/add-prod-shell
Add production mode to dev shell
2019-04-15 07:40:39 -07:00
Dan Abramov
947e3c2c04 Add production mode to dev shell 2019-04-15 15:39:25 +01:00
Brian Vaughn
7489b8508b Merge pull request #159 from gaearon/l-to-the-r-to-the-u
Use LRU for encoded strings
2019-04-15 07:09:10 -07:00
Dan Abramov
255385d255 Use LRU for encoded strings 2019-04-15 14:42:12 +01:00
Dan
f569d27f86 Add a stress test for tree traversal 2019-04-15 01:52:15 +01:00
Brian Vaughn
b76372c93d Fixed an edge case profiling bug where the number of commits was wrong 2019-04-13 18:29:39 -07:00
Brian Vaughn
7f6fdfea95 Add package commands for creating dev builds for easier debugging 2019-04-13 18:25:56 -07:00
Brian Vaughn
00f6466ec1 Temporarily disabled hooks lint failure for Tree useEffect 2019-04-13 15:49:06 -07:00
Brian Vaughn
97f089bdfe Merge pull request #148 from gaearon/scroll-consistent
Consistently scroll component name into view
2019-04-13 15:39:25 -07:00
Brian Vaughn
518f3d75f8 Tweaked an inline comment. 2019-04-13 15:38:56 -07:00
Brian Vaughn
b2cf896e8c Fixed misplaced padding in Tree 2019-04-13 15:33:10 -07:00
Brian Vaughn
236f47f073 Tweaked .eslintignore and .gitignore 2019-04-13 15:32:26 -07:00
Brian Vaughn
86f9293376 Merge pull request #154 from gaearon/resize-hilite
Adjust highlighting on window resize
2019-04-13 15:25:17 -07:00
Brian Vaughn
d5266f9409 Merge pull request #155 from gaearon/view-dom-inspect
View DOM button opens Elements tab
2019-04-13 15:23:09 -07:00
Brian Vaughn
453a06a465 Merge pull request #150 from gaearon/bump-hooks-plugin
Bump React Hooks plugin
2019-04-13 15:20:08 -07:00
Brian Vaughn
826cac0070 Merge pull request #149 from gaearon/dont-reset
Don't reset selected item on search mismatch or exit
2019-04-13 15:19:38 -07:00
Dominic Gannaway
9ebe1768a8 Experimental Event API: Redesign event responder propagation (#15408)
* Event API: Redesign event instance propagation
2019-04-13 20:37:39 +01:00
Dan
ce335b8975 View DOM button opens Elements tab 2019-04-13 18:59:47 +01:00
Dan
6d53a2ec10 Adjust highlighting on window resize 2019-04-13 18:24:59 +01:00
Dan
9162b7165a Prefer to keep the start anchor visible 2019-04-13 16:49:10 +01:00
Dan
6d70028a26 Bump React Hooks plugin 2019-04-13 16:38:34 +01:00
Dan
55dcfe25e8 Don't reset selected item on search mismatch or exit 2019-04-13 16:20:16 +01:00
Brian Vaughn
ca7eb3c829 Changed highlight-on-search behavior to use TreeContext 2019-04-12 18:14:46 -07:00
Dan Abramov
097d0386b1 Track search navigation in DOM 2019-04-12 18:14:46 -07:00
Brian Vaughn
7145c78325 Merge pull request #147 from gaearon/no-propagation
Polish some mouse interactions
2019-04-12 18:09:16 -07:00
Dan
ba9c763954 Consistently scroll component name into view 2019-04-13 01:58:05 +01:00
Dan
454bcf1e01 Polish some mouse interactions 2019-04-13 01:07:35 +01:00
Philipp Spiess
a30e7d992e act() tests - Reuse and properly unmount containers (#14974) 2019-04-12 23:53:36 +01:00
Brian Vaughn
1e08261975 Added missing instruction to Chrome install steps 2019-04-12 15:08:14 -07:00
Brian Vaughn
818255dfde Merge pull request #145 from bvaughn/deploy-chrome-updates
Auto-update Chrome extension
2019-04-12 15:02:11 -07:00
Brian Vaughn
801bb5e33a Udpated Firefox installation instructions 2019-04-12 14:45:39 -07:00
Brian Vaughn
670d1348f1 Chrome build+deploy script auto-increment a prerelease version 2019-04-12 14:42:34 -07:00
Brian Vaughn
26361427ae Auto-update Chrome extension 2019-04-12 13:46:05 -07:00
Nicolas Gallagher
8cf963c6c3 React events: ignore device buttons that aren't for primary interactions (#15402)
The Pointer Events spec mentions that the value of `button` in a nativeEvent
can be anything between 0 and 5 for "down" events. We only care about those
with a value of 0.
2019-04-12 13:36:00 -07:00
Andrew Clark
38bd570d41 Stop tracking bundle sizes (#15404)
* [sizebot] Fail gracefully if CI returns invalid response

Moves the `response.json()` call into the catch block.

* Stop tracking bundle sizes
2019-04-12 13:33:27 -07:00
Brian Vaughn
9c1dad5059 react-window 1.8.0 2019-04-12 10:57:56 -07:00
Brian Vaughn
b18c836ef5 Merge branch 'smart-scroll' of https://github.com/gaearon/react-devtools-experimental into gaearon-smart-scroll 2019-04-12 10:56:27 -07:00
Brian Vaughn
dbd1d6b0bd Firefox only supports peristent background extensions so I've removed the persistent:false flag 2019-04-12 10:20:23 -07:00
Dan Abramov
403f150ade Use smart scrolling 2019-04-12 18:13:26 +01:00
Brian Vaughn
8f17ade7e5 Circle CI config changes 2019-04-12 09:27:53 -07:00
Brian Vaughn
af8a5d9311 Added devEngines entry to package.json 2019-04-12 09:24:16 -07:00
Brian Vaughn
a57b6dbef5 Merge pull request #133 from bvaughn/tests
Automated tests [WIP]
2019-04-12 09:22:11 -07:00
Brian Vaughn
be930d5490 Use Circle CI to run lint, prettier, flow, and tests 2019-04-12 09:17:42 -07:00
Brian Vaughn
7bb2299de4 Moved __DEV__ setup from setupTests to setupEnv 2019-04-12 08:55:29 -07:00
Brian Vaughn
e0ffa2b88d Moved a few vars inside of the setupTest beforeEach block 2019-04-12 08:55:29 -07:00
Brian Vaughn
158b0b5567 Added expand/collapse tests; chronologically ordered snapshots 2019-04-12 08:55:29 -07:00
Brian Vaughn
16a7119bf2 Added a simple Suspense test 2019-04-12 08:55:29 -07:00
Brian Vaughn
4ad85b26c0 Cleaned up setup/polyfills 2019-04-12 08:55:29 -07:00
Brian Vaughn
81183b1492 Named snapshots. Tests use act() abstraction. 2019-04-12 08:55:29 -07:00
Brian Vaughn
5d6a2082cc Updated React test utils for newer version of act() 2019-04-12 08:55:29 -07:00
Brian Vaughn
1bdae952b5 Added separate mount+update tests 2019-04-12 08:55:29 -07:00
Brian Vaughn
25e918b4d9 Added [root] indicator to Store snapshot reprensentation 2019-04-12 08:55:29 -07:00
Brian Vaughn
4926d160d6 Removed unnecessary configurable Bridge batch duration 2019-04-12 08:55:29 -07:00
Brian Vaughn
9fb794b6ed Added multi-test setup logic 2019-04-12 08:55:29 -07:00
Brian Vaughn
7621df5baf Initial example test. Will iterate from here. 2019-04-12 08:55:29 -07:00
Brian Vaughn
7aadcdf624 Use :hidden attribute to collapse props/hooks 2019-04-12 08:53:41 -07:00
Brian Vaughn
ae7ea00e06 Fix small sizing issue with expand collapse toggle 2019-04-12 08:42:27 -07:00
Brian Vaughn
da4accda31 Added expand/collapse toggles to custom hooks 2019-04-12 08:39:03 -07:00
Dominic Gannaway
3438e5ce87 Experimental Event API: Add Hover onUnmount support (#15394) 2019-04-12 13:26:27 +01:00
Nicolas Gallagher
805e7f8733 React events: add unmounting to Focus (#15396) 2019-04-12 12:23:03 +01:00
Dominic Gannaway
543353a043 Experimental Event API: Remove "listener" from event objects (#15391) 2019-04-12 11:53:40 +01:00
Andrew Clark
ed6798405d Better message when CI for base commit is pending 2019-04-11 19:24:22 -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
Brian Vaughn
94810b2b5a Add Git revision to extension manifests 2019-04-11 19:06:07 -07:00
Nicolas Gallagher
4e59d4f5d2 React events: add onHoverMove support (#15388) 2019-04-11 18:59:05 -07:00
Brian Vaughn
9a0cf68a4d Add Git revision to build version 2019-04-11 18:44:44 -07:00
Brian Vaughn
3ea5fac959 Enable text to wrap within error boundary stacks 2019-04-11 18:29:06 -07:00
Brian Vaughn
f32b65d7b0 Merge pull request #135 from lucasecdb/fiber-info-overflow
Fix fiber info sidepanel not scrollable
2019-04-11 18:21:57 -07:00
Lucas Cordeiro
2671e7e0e0 Fix fiber info sidepanel not scrollable 2019-04-11 21:38:57 -03:00
Andrew Clark
cdfb06e38b Fix path to results.json 2019-04-11 17:20:14 -07:00
Brian Vaughn
9642d26674 Added ErrorBoundary with GitHub bug link 2019-04-11 17:19:16 -07:00
Dan Abramov
da508fc23f Merge pull request #126 from bvaughn/js-hover
Ignore hover when navigating with keyboard
2019-04-12 01:16:26 +01:00
Andrew Clark
de75903272 Fix CI (#15393)
* Revert "Bump scheduler version to 0.14.0"

This reverts commit 687e4fb6f7.

* Store results.json as CI build artifact
2019-04-11 16:43:33 -07:00
Brian Vaughn
367249c175 Don't drill into owners list if no owner metadata is available 2019-04-11 14:00:27 -07:00
Andrew Clark
687e4fb6f7 Bump scheduler version to 0.14.0
Releasing this early for React Native
2019-04-11 13:42:34 -07:00
Nicolas Gallagher
45473c94cd React events: Press event fixes (#15386)
1. Fix hiding context menu for longpress via touch.
2. Fix scrolling of viewport for longpress via spacebar key.
3. Add tests for anchor-related behaviour and preventDefault.
4. Add a deactivation delay for forced activation
5. Add pointerType to Press events.

NOTE: this currently extends pointerType to include `keyboard`.

NOTE: React Native doesn't have a deactivation delay for forced activation, but this is possibly because of the async bridge meaning that the events aren't dispatched sync.
2019-04-11 13:20:21 -07:00
Dominic Gannaway
9672cf621b Experimental Event API: adds stopPropagation by default to Press (#15384) 2019-04-11 20:00:20 +01:00
Brian Vaughn
75657c81e8 Merge branch 'keyboard-stuff' of https://github.com/gaearon/react-devtools-experimental 2019-04-11 11:55:39 -07:00
Dan Abramov
38b7cf5693 Ignore hover when navigating with keyboard 2019-04-11 13:27:49 +01:00
Dan Abramov
0281a0d905 Add a missing dep 2019-04-11 13:20:32 +01:00
Dominic Gannaway
a9eff329c6 Remove TouchHitTarget SSR logic to prevent issues with mouse events (#15381) 2019-04-11 12:05:26 +01:00
Dominic Gannaway
c9841001b0 Experimental Event API: preventDefault handling for anchors (#15383) 2019-04-11 12:04:39 +01:00
Brian Vaughn
a5eb96fbc0 Merge pull request #134 from sophiebits/bridge-batch
Improve bridge batching logic
2019-04-10 17:21:30 -07:00
Sebastian Markbåge
c25c59c808 Apply the Just Noticeable Difference to suspense timeouts (#15367)
* Apply the Just Noticeable Difference boundary

* Clamp suspense timeout to expiration time
2019-04-10 17:16:27 -07:00
Sophie Alpert
7c13ea2f2b Improve bridge batching logic
Fixes #132.
2019-04-10 16:31:11 -07:00
Brian Vaughn
40469a190e Fixed horizontal alignment for collapsable hooks 2019-04-10 12:47:51 -07:00
Brian Vaughn
84a5a13525 Editable name not text-selectable 2019-04-10 12:37:20 -07:00
Brian Vaughn
e9f385591e Double clicking on a name toggles expanded state in KeyValue 2019-04-10 12:36:26 -07:00
Brian Vaughn
4f254c0a05 Refactored KeyValue toggle so columns with toggles align better below those without 2019-04-10 11:44:45 -07:00
Dominic Gannaway
3e2e930d62 Fixes a Flow type merge conflict (#15378) 2019-04-10 19:33:05 +01:00
Dan Abramov
952c8cda00 Fix a bug that caused it to jump over nodes when pressing too fast 2019-04-10 19:30:45 +01:00
Brian Vaughn
f0fb1805fe Added new color-expand-collapse-toggle CSS var 2019-04-10 11:03:32 -07:00
Brian Vaughn
3e19b164b5 Merge branch 'collapse-props' of https://github.com/lucasecdb/react-devtools-experimental into lucasecdb-collapse-props 2019-04-10 11:03:04 -07:00
Lucas Cordeiro
944a6192e2 Use button instead of div for a11y 2019-04-10 15:01:05 -03:00
Nicolas Gallagher
7fc91f17c9 React events: add onPressMove and pressRetentionOffset to Press (#15374)
This implementation differs from equivalents in React Native in the following ways:

1. A move during a press will not cancel onLongPress.
2. A move to outside the retention target will cancel the press and not
reactivate when moved back within the retention target.
2019-04-10 10:52:50 -07:00
Dominic Gannaway
dd9cef9fc0 Experimental Event API: Add targets and responder utility method for finding targets (#15372) 2019-04-10 18:52:34 +01:00
Dan Abramov
6420f11d65 Left and right arrows only traverse parents 2019-04-10 18:49:52 +01:00
Lucas Cordeiro
2d516199ea Update opener icon and remove negative margin 2019-04-10 14:47:39 -03:00
Brian Vaughn
0aacc2547e Merge pull request #123 from gaearon/focus-keyboard
Picking a DOM node focuses the tree
2019-04-10 10:31:05 -07:00
Lucas Cordeiro
99a1e07aa6 Fix flow type 2019-04-10 14:28:48 -03:00
Lucas Cordeiro
0f955980a3 Add collapsible icon for object and array types 2019-04-10 14:28:48 -03:00
Dan Abramov
1c381c588a Picking a DOM node focuses the tree 2019-04-10 18:27:40 +01:00
Brian Vaughn
88e51adc35 Merge pull request #122 from gaearon/prevent
Prevent default on all key navigations
2019-04-10 10:17:12 -07:00
Brian Vaughn
4b0424fbed Flow fix 2019-04-10 10:16:09 -07:00
Brian Vaughn
268a7cb5b4 Moved blur/focus up to the AutoSizer wrapper and removed an effect+ref 2019-04-10 10:14:21 -07:00
Brian Vaughn
caa74472f2 Replaced nested ternary 2019-04-10 10:01:03 -07:00
Brian Vaughn
6836f15924 Tweaked inactive CSS colors 2019-04-10 09:56:21 -07:00
Brian Vaughn
d9ef0839a4 Merge branch 'inactive-window' of https://github.com/lucasecdb/react-devtools-experimental into lucasecdb-inactive-window 2019-04-10 09:51:29 -07:00
Dan Abramov
5b480a85cb Prevent default on all key navigations 2019-04-10 17:46:34 +01:00
Brian Vaughn
11c03bf7bc Merge pull request #120 from gaearon/mutation-index
Update selected index after mutation
2019-04-10 09:35:00 -07:00
Brian Vaughn
7263e768e5 Merge pull request #116 from bvaughn/issues/105
Add collapse/toggle UI to Tree
2019-04-10 09:31:12 -07:00
Brian Vaughn
56be358847 Merge pull request #114 from gaearon/lazy-sync
Send the bridge sync event lazily
2019-04-10 09:28:54 -07:00
Dan Abramov
f1a8bd2923 Update selected index after mutation 2019-04-10 17:28:36 +01:00
Brian Vaughn
f89f2b2146 Reverted misguided index/collapsed behavior 2019-04-10 09:23:24 -07:00
Brian Vaughn
ba46f2df0a Merge pull request #118 from gaearon/required-title
Add missing Button titles
2019-04-10 09:10:24 -07:00
Brian Vaughn
98240f18ae Merge pull request #117 from gaearon/hide-shell
Put DevTools in dev shell above the inspector
2019-04-10 09:10:10 -07:00
Brian Vaughn
74c9904e5d Rewrote weightDelta calculation to be more readable based on PR feedback 2019-04-10 08:59:43 -07:00
Brian Vaughn
dd84e8ff2b Newly selected components always auto-expand their ancestors 2019-04-10 08:57:42 -07:00
Brian Vaughn
1f7f0ea691 Update Store.getIndexOfElementID to take isCollapsed into account 2019-04-10 07:53:06 -07:00
Brian Vaughn
b004a79415 Reverted some unnecessary changes to TreeContext after Dan's PR 101 was merged 2019-04-10 07:45:45 -07:00
Brian Vaughn
102267b1d6 Renamed _numElements attribute based on PR feedback 2019-04-10 07:42:32 -07:00
Brian Vaughn
61203f77cf Hide toggle arrows in owners list mode 2019-04-10 07:42:32 -07:00
Brian Vaughn
55b3635f28 Left/right arrow toggles node collapsed state as well 2019-04-10 07:42:32 -07:00
Brian Vaughn
f7212d8035 Upgrade react-window to fix a scroll-to bug 2019-04-10 07:42:32 -07:00
Brian Vaughn
4c522c4c38 Selected search result auto-opens collapsed nodes when necessary.
Also fixed an unrelated bug about when we reset search index when text changes.
2019-04-10 07:42:32 -07:00
Brian Vaughn
b6df86c90c Added toggle button to Tree > Element views 2019-04-10 07:38:40 -07:00
Brian Vaughn
79827c535b Added isToggled boolean to tree nodes and toggleIsCollapsed() method to Store 2019-04-10 07:38:40 -07:00
Brian Vaughn
0decb17837 Merge pull request #101 from gaearon/find-nit
Pressing next forces search to select
2019-04-10 07:38:28 -07:00
Dan Abramov
1102fc5c11 Refactor: extract a variable 2019-04-10 15:25:03 +01:00
Dan Abramov
3eca0bbe61 Use heuristic suggested by @sophiebits 2019-04-10 15:08:13 +01:00
Dan
07299828c9 Pressing next forces search to select 2019-04-10 14:57:39 +01:00
Dan Abramov
75a4312d87 Add missing Button titles 2019-04-10 14:40:41 +01:00
Dan Abramov
84478a41ff Put DevTools in dev shell above the inspector 2019-04-10 14:26:33 +01:00
Dominic Gannaway
c64b330032 Move EventTypes to ReactTypes (#15364) 2019-04-10 09:55:56 +01:00
Sebastian Markbåge
4c78ac0b9d Track Event Time as the Start Time for Suspense (#15358)
* Track the earliest event time in this render

Rebase

* Track the time of the fallback being shown as an event time

When we switch back from fallback to content, we made progress and we track
the time from when we showed the fallback in the first place as the
last time we made progress.

* Don't retry if synchronous

* Only suspend when we switch to fallback mode

This ensures that we don't resuspend unnecessarily if we're just retrying
the same exact boundary again. We can still unnecessarily suspend
for nested boundaries.

* Rename timedOutAt to fallbackExpirationTime

* Account for suspense in devtools suspense test
2019-04-09 18:59:39 -07:00
Brian Vaughn
6d222080ad Format logElementToConsole() slightly 2019-04-09 18:13:11 -07:00
Andrew Clark
875d05d553 Include full error messages in React Native build (#15363)
The React Native build does not minify error messages in production,
but it still needs to run the error messages transform to compile
`invariant` calls to `ReactError`. To do this, I added a `noMinify`
option to the Babel plugin. I also renamed it from
`minify-error-messages` to the more generic `transform-error-messages`.
2019-04-09 16:40:19 -07:00
Eli White
1b2159acc3 [React Native] measure calls will now call FabricUIManager (#15324)
* [React Native] Add tests to paper renderer for measure, measureLayout

* [React Native] measure calls will now call FabricUIManager

The Fabric renderer was previously calling the paper UIManager's measure calls and passing the react tag. This PR changes the renderer to now call FabricUIManager passing the node instead.

One of the parts of this that feels more controversial is making NativeMethodsMixin and ReactNative.NativeComponent warn when calling measureLayout in Fabric. As Seb and I decided in https://github.com/facebook/react/pull/15126, it doesn't make sense for a component created with one of these methods to require a native ref but not work the other way around. For example: a.measureLayout(b) might work but b.measureLayout(a) wouldn't. We figure we should keep these consistent and continue migrating things off of NativeMethodsMixin and NativeComponent.

If this becomes problematic for the Fabric rollout then we should revisit this.

* Fixing Flow

* Add FabricUIManager to externals for paper renderer

* import * as FabricUIManager from 'FabricUIManager';

* Update tests

* Shouldn't have removed UIManager import

* Update with the new tests
2019-04-09 15:10:15 -07:00
Lucas Cordeiro
1c57ca0a1c Use focus state from elements tree instead of ownerDocument 2019-04-09 19:04:03 -03:00
Lucas Cordeiro
26106a4b9d Add check for inactive window on selected element 2019-04-09 19:03:59 -03:00
Eli White
c7a959982b [React Native] Add tests to paper renderer for measure, measureLayout (#15323)
* [React Native] Add tests to paper renderer for measure, measureLayout

* Update tests

* Shouldn't have removed UIManager import
2019-04-09 14:49:07 -07:00
Dan Abramov
43bb821f60 Send the bridge sync event lazily 2019-04-09 20:04:33 +01:00
Brian Vaughn
edc598e62a Fixed Tree minWidth initial case to fill 100% width 2019-04-09 11:43:49 -07:00
Brian Vaughn
1cc219009a Tweaked owners stack CSS to fix another overflow issue 2019-04-09 11:12:39 -07:00
Brian Vaughn
49f6a22b5b Remember max Tree width as new nested items are rendered 2019-04-09 10:58:43 -07:00
Brian Vaughn
d6bd3dc503 Fixed owner stack size calculation bug that sometimes caused bad overflow 2019-04-09 10:18:04 -07:00
Brian Vaughn
f1fc4b0331 Merge pull request #108 from bvaughn/reach-ui-menubutton
Use @reach MenuButton for owner stack menu [WIP]
2019-04-09 08:58:08 -07:00
Brian Vaughn
dbf6942512 Added (local) fork of @reach/portal to unblock OwnersStack MenuButton PR 2019-04-09 08:54:43 -07:00
Brian Vaughn
a29ab9ab79 Tree arrow navigation respects event.defaultPrevented
This prevents Reach MenuButton operations from also changing the tree selection in the background
2019-04-09 08:37:34 -07:00
Brian Vaughn
163bc234df Disable text selection for OwnersStack buttons 2019-04-09 08:36:54 -07:00
Brian Vaughn
db629fa073 Updated OwnersStack CSS to properly override React styles 2019-04-09 08:30:24 -07:00
Dan Abramov
4bde8f6503 Merge pull request #103 from gaearon/sad-one-way
Make DOM selection binding one-way
2019-04-09 13:25:08 +01:00
Dominic Gannaway
aece8119cf Refactor EventComponent logic + add onOwnershipChange callback (#15354) 2019-04-09 12:47:32 +01:00
Dan Abramov
153666b484 Merge pull request #107 from sophiebits/flicker
pointer-events: none to fix flicker on Overlay "tip"
2019-04-09 11:40:47 +01:00
Andrew Clark
183d1f42ed Fix: Measure expiration times relative to module initialization (#15357)
We use bitwise operations to compute expiration times, which means they
need to be smaller than 31 bits. So we measure times relative to module
initialization, similar to `performance.now`.

This was already working in the old fiber scheduler, but we didn't have
a test for it.
2019-04-08 19:44:06 -07:00
Brian Vaughn
ba99444515 Use @reach MenuButton for owner stack menu 2019-04-08 18:34:48 -07:00
Sophie Alpert
a2d84fa613 pointer-events: none to fix flicker on Overlay "tip"
If click-to-inspect then hover an element in just the right place, it flickers between two elements because this "tip" element catches the hover. This should fix it.
2019-04-08 18:26:30 -07:00
Dan
72eccb465d Make DOM selection binding one-way 2019-04-09 01:30:40 +01:00
Dan Abramov
267ab34fbd Merge pull request #99 from gaearon/sync-tabs
Sync DevTools Elements and Components tabs
2019-04-08 23:55:16 +01:00
Dan
3b793953b1 Keep DOM selection if last $0 resolves to same component 2019-04-08 23:46:47 +01:00
Dan
436912ab2d Remove unnecessary logic 2019-04-08 23:35:01 +01:00
Dan
7aecd58d81 Nits 2019-04-08 23:28:31 +01:00
Dan
c91676b557 Don't change browser selection unless React selection changed 2019-04-08 21:57:13 +01:00
Brian Vaughn
5db5e40bf1 Replaced Agent setInterval with throttle+memoize 2019-04-08 13:50:04 -07:00
Dan Abramov
388677fcbc Merge branch 'master' into continuous-select 2019-04-08 20:50:58 +01:00
Dan Abramov
4a301bd0e0 Sync DevTools Elements and Components tabs 2019-04-08 20:41:01 +01:00
Brian Vaughn
44ecff31e3 Fixed an unpleasant interaction with owners modal "..." button 2019-04-08 12:20:45 -07:00
Brian Vaughn
e43cfa0239 Don't re-measure owners stack sizes unnecessarily 2019-04-08 12:05:07 -07:00
Brian Vaughn
174125c854 Merge branch 'master' of github.com:bvaughn/react-devtools-experimental 2019-04-08 11:41:56 -07:00
Brian Vaughn
58ae3c63a8 Added export-log icon. Removed unnecessary variable assignment. 2019-04-08 11:41:25 -07:00
Dan Abramov
ab89d6500f Fix missing key 2019-04-08 19:01:28 +01:00
Brian Vaughn
fefb2bc99b Merge branch 'inspect-log' of https://github.com/gaearon/react-devtools-experimental into gaearon-inspect-log 2019-04-08 10:41:58 -07:00
Brian Vaughn
b3ba758798 Updated flow-bin 2019-04-08 10:40:46 -07:00
Brian Vaughn
7115408751 Added for itemData 2019-04-08 10:40:40 -07:00
Dan Abramov
5b120d6b24 Add a separate button for logging values 2019-04-08 18:39:37 +01:00
Dan Abramov
b176cd4414 Refactor: split inspectElementRaw 2019-04-08 18:37:36 +01:00
Brian Vaughn
14105e865a Merge pull request #92 from gaearon/highlight-on-hover
Select DOM nodes on hover
2019-04-08 10:23:56 -07:00
Dan Abramov
52014671bf Make Flow happy 2019-04-08 18:03:48 +01:00
Dan Abramov
c6ee445ea9 Address review 2019-04-08 18:00:48 +01:00
Dan Abramov
6538e7141a Add a comment 2019-04-08 17:58:12 +01:00
Dan Abramov
39223239bb Select DOM nodes on hover 2019-04-08 17:58:12 +01:00
Dan Abramov
cb164eb9fb Merge pull request #91 from gaearon/fix-scroll
Fix spurious autoscroll
2019-04-08 17:51:35 +01:00
砖家
b4bc33a584 Fix areHookInputsEqual method warning params order (#15345)
* Fix areHookInputsEqual method  warning params order

* FIX areHookInputsEqual test
2019-04-08 17:14:42 +01:00
Brian Vaughn
c619d56b1c Merge pull request #93 from gaearon/keep-mounted
Preserve state when switching tabs
2019-04-08 08:43:31 -07:00
Brian Vaughn
e86d7b51ea Merge pull request #94 from gaearon/rendered-by
Rename "owner stack" label to "rendered by"
2019-04-08 08:20:56 -07:00
Dominic Gannaway
29fb5862fb Move EventComponent state creation to complete phase + tests (#15352) 2019-04-08 16:02:20 +01:00
Dan Abramov
edfab66104 Rename "owner stack" label to "rendered by" 2019-04-08 15:40:40 +01:00
Dan Abramov
132529da79 Preserve state when switching tabs 2019-04-08 15:29:51 +01:00
Dan
0a6d637619 Fix spurious autoscroll 2019-04-08 00:51:31 +01:00
Brian Vaughn
2ba3ee6c1c Merge pull request #86 from gaearon/owner-stack-id
Preserve selection on exiting owner mode
2019-04-07 15:42:43 -07:00
Brian Vaughn
7e2ef6a34e Merge pull request #87 from gaearon/bump-overscan
Bump overscan to 3
2019-04-07 15:36:20 -07:00
Brian Vaughn
77267e8544 Fixed Toggle Flow prop types 2019-04-07 15:34:35 -07:00
Brian Vaughn
f61507158e Merge branch 'hristo-kanchev-owner-stack-enhancement' 2019-04-07 15:33:42 -07:00
Brian Vaughn
e489c8ac8e Owners stack modal behaves and looks more like a modal 2019-04-07 15:32:13 -07:00
Brian Vaughn
2ac815784b Removed unnecessary layout effect in favor of a setState 2019-04-07 15:19:17 -07:00
Dan Abramov
a9c20f0b36 Merge pull request #88 from gaearon/remove-ring
Remove tree focus ring
2019-04-07 20:16:06 +01: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
Brian Vaughn
ae2e8128bd Merge pull request #89 from gaearon/toggle-fix
Pass Toggle label through
2019-04-07 10:54:35 -07:00
Dan
5a118701b0 Pass Toggle label through 2019-04-07 18:44:11 +01:00
Brian Vaughn
2e5e88e127 Cleaned up is-overflowing hook and dependencies 2019-04-07 10:34:44 -07:00
Dan
2607b39fe1 Remove tree focus ring 2019-04-07 18:20:34 +01:00
Brian Vaughn
5b6dbb8dd7 Replaced some passive effects with layout effects to avoid flash of overflowed owners 2019-04-07 10:01:18 -07:00
Brian Vaughn
df00a9639e Removed some unnecessary functions 2019-04-07 09:58:34 -07:00
Dan
a42a3a2d72 Bump overscan 2019-04-07 17:55:27 +01:00
Brian Vaughn
850dda0fb9 Cleaned up an old Overlay helper function 2019-04-07 09:53:34 -07:00
Brian Vaughn
252a87efe5 Use 'classnames' in TabBar to simplify an attribute 2019-04-07 09:51:54 -07:00
Brian Vaughn
9255ad1025 Replaced "colon" icon with more standard 3-dot "more" 2019-04-07 09:46:44 -07:00
Dan
f2951fb51f Preserve selection on exiting owner mode 2019-04-07 17:43:10 +01:00
Brian Vaughn
9a2f9ac880 Moved getElementDimensions() back into Overlay component 2019-04-07 09:42:52 -07:00
Brian Vaughn
d686b9d890 Merge branch 'owner-stack-enhancement' of https://github.com/hristo-kanchev/react-devtools-experimental into hristo-kanchev-owner-stack-enhancement 2019-04-07 09:13:33 -07:00
Brian Vaughn
2b868821d5 Improved keyboard navigation for tabs, interactions, and fiber-commits 2019-04-07 09:00:52 -07:00
Brian Vaughn
44c0febd23 Profiler shows commit times and durations for selected fiber 2019-04-07 08:36:37 -07:00
Hristo Kanchev
2620050abf Removed unneeded min-height. Using throttle for resize function. 2019-04-07 11:48:35 +02:00
Hristo Kanchev
ce04f531d4 Implemented new OwnerStack UI enhancement 2019-04-07 11:37:12 +02:00
Brian Vaughn
5334249bda Fixed a typo in flamegraph duration label 2019-04-06 18:01:44 -07:00
Brian Vaughn
d766d3b2e5 Throttle screenshots to reduce impact on performance. 2019-04-06 13:58:55 -07:00
Nicolas Gallagher
81a61b1d1a React events: add delay props to Press module (#15340)
* Add delay props to Press event module
* Minor naming changes to Hover events
* Add examples to react-events README
2019-04-06 13:47:28 -07:00
Brian Vaughn
bfcef10af3 Merge pull request #84 from gaearon/dead
Remove dead code
2019-04-06 13:37:50 -07:00
Dan
9fc2a3400c Remove dead code 2019-04-06 21:36:08 +01:00
Dan
99593444b9 Address review 2019-04-06 21:30:57 +01:00
Dan
785bb9f56c Continuously update tree selection in DOM inspection mode 2019-04-06 20:27:36 +01:00
Dan Abramov
985fe59826 Merge pull request #81 from gaearon/overlay-owner
Show owner in DOM highilght overlay
2019-04-06 18:26:50 +01:00
Dan
5eec8aed33 Nit 2019-04-06 18:26:17 +01:00
Dan
ab9c1b84c8 Show owner in DOM highilght overlay 2019-04-06 17:07:06 +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
Dan Abramov
72d9f0597a Merge pull request #71 from gaearon/suspense-special
Fix Suspense fragment edge cases
2019-04-05 23:59:17 +01:00
Dan
d3d5c050bd Naming 2019-04-05 23:45:34 +01:00
Dan
7a03c5a885 Update the commit tree to assume operations do not repeat 2019-04-05 23:42:02 +01:00
Dan
80d9d8d841 Fix profiler and nits 2019-04-05 23:34:27 +01:00
Dan
0f536bba5c Rewrite the Suspense logic 2019-04-05 23:12:57 +01:00
Dan Abramov
d6257d382d Expand the test fixture 2019-04-05 21:49:37 +01:00
Dan
9bcd5b2576 Fix Suspense fragment edge cases 2019-04-05 21:49:37 +01:00
Dan Abramov
387ad54d80 Merge pull request #75 from gaearon/fix-double-add
Fix double-adding fibers when traversing
2019-04-05 18:45:42 +01:00
Dan Abramov
2a5b8a9206 Hard crash 2019-04-05 18:41:26 +01:00
Dan Abramov
96a7adf49e Add error logs in __DEBUG__ 2019-04-05 18:27:02 +01:00
Dan Abramov
9170e5695a Fix double-adding fibers when traversing 2019-04-05 18:18:39 +01:00
Brian Vaughn
0c8129c78a Sync selected Profiler node back to the Components tab
Also show element keys in Profiler charts
2019-04-05 08:47:23 -07:00
Brian Vaughn
d1a5346c48 Improved keyboard UX and focus UI for Tree and OwnersStack 2019-04-05 08:08:02 -07:00
Dan Abramov
632647fbac Merge pull request #61 from gaearon/toggle-suspense-2
Allow to toggle Suspense in Components pane
2019-04-05 13:22:41 +01:00
Dan
b8245de5a1 Nits 2019-04-05 13:19:39 +01:00
Dan Abramov
48a5aca127 Fix highlighting timed out Suspense DOM node 2019-04-05 13:19:35 +01:00
Dan Abramov
4f5437edf7 Allow to toggle Suspense in Components pane 2019-04-05 13:19:30 +01:00
Nicolas Gallagher
958b6173fd Add delay props to Hover event module (#15325) 2019-04-05 12:23:51 +01:00
Nicolas Gallagher
c3cc936dae Add Hover,Focus,Press docs to REAMDE (#15328) 2019-04-05 11:58:04 +01:00
Brian Vaughn
bfbb4ac545 Merge pull request #72 from gaearon/search-bug
Don't move selection unless search text increased length
2019-04-04 17:55:12 -07:00
Dan
a8e46c67e6 Don't move selection unless search text increased length 2019-04-05 00:49:27 +01:00
Andrew Clark
49595e921d [New Scheduler] Fix: Suspending an expired update (#15326)
When an async update expires, React renders at the expiration time that
corresponds to the current time, not at the original update's expiration
time. That way, all the expired work in the tree is flushed in a
single batch.

This is implemented inside `renderRoot` by comparing the next render
expiration time to the current time. If the current time is later,
`renderRoot` will restart at the later time.

Because of poor factoring, the check is currently performed right before
entering the work loop. But the work loop is usually entered multiple
times in a single callback: each time a component throws or suspends.
This led to an infinite loop where React would detect that an update
expired, restart at the current time, make a bit of progress, suspend,
check for expired work again, and start the loop again.

I fixed this by moving the expired work check to the beginning of
`renderRoot`, so that it is not performed every time something suspends.
This isn't ideal, because you could technically still fall into a loop
if more than 10ms lapse in between exiting `renderRoot` and entering it
again. The proper fix is to lift the check outside of `renderRoot`
entirely so that the function can restart without checking for expired
work again. Since this is exceedingly unlikely (and this whole thing is
still behind a flag), I'll do the better fix in an already-planned
follow up to fork `renderRoot` into separate functions for sync and
async work.
2019-04-04 16:31:22 -07:00
Brian Vaughn
16951fe7fb Merge pull request #70 from gaearon/free-debug
Explicitly guard debug calls
2019-04-04 16:12:45 -07:00
Dan
2928a0be74 Explicitly guard debug calls 2019-04-05 00:03:17 +01:00
Dominic Gannaway
b93a8a9bb8 Experimental event API: refactor responder modules for lifecycle inclusion (#15322) 2019-04-04 23:28:23 +01:00
Brian Vaughn
9b05184ccb Merge pull request #63 from gaearon/smarter-search-match
Match search at word boundaries
2019-04-04 14:41:08 -07:00
Brian Vaughn
6c5c2cd3ad Renamed innerElementType -> InnerElementType to avoid confusing hooks lint rule 2019-04-04 14:10:14 -07:00
Brian Vaughn
8d435595cd Added truncation UI indicator for hooks. Addressed lint rule violations. 2019-04-04 14:09:10 -07:00
Brian Vaughn
11d068d794 Merge branch 'fix-nested-hooks' of https://github.com/gaearon/react-devtools-experimental into gaearon-fix-nested-hooks 2019-04-04 13:54:41 -07:00
Brian Vaughn
64b0fd8ecd Fixed owners header font family too 2019-04-04 13:52:53 -07:00
Brian Vaughn
43782e6696 Merge branch 'larger-items' of https://github.com/gaearon/react-devtools-experimental into gaearon-larger-items 2019-04-04 13:48:24 -07:00
Brian Vaughn
93f83d27dd Merge pull request #66 from gaearon/dont-dismiss-menu
Stop mouseup propagation while inspecting
2019-04-04 13:47:59 -07:00
Dan Abramov
9351c8070d Fix it all 2019-04-04 19:54:56 +01:00
Dan Abramov
18e337707a Stop mouseup propagation while inspecting 2019-04-04 19:52:18 +01:00
Dan Abramov
194f523331 Add size to owner stack items 2019-04-04 19:36:04 +01:00
Dan Abramov
8478a526e6 Don't crash for deeply nested Hooks 2019-04-04 19:28:42 +01:00
Brian Vaughn
ded2ce03ee Renamed TreeWrapper to innerElementType 2019-04-04 10:08:48 -07:00
Brian Vaughn
c86793ef18 Merge branch 'a11y-tree' of https://github.com/gaearon/react-devtools-experimental into gaearon-a11y-tree 2019-04-04 09:54:46 -07:00
Dan Abramov
2afda3de37 Add back regex support 2019-04-04 17:05:34 +01:00
Dan Abramov
0f0062a71c Fix special cases 2019-04-04 17:00:35 +01:00
Nicolas Gallagher
937d262f55 React events: keyboard press, types, tests (#15314)
* Add HoverProps type
* Add more Hover event module tests
* Add more Press event module tests
* Change default longPress delay from 1000 to 500
* Rename dispatchPressEvent -> dispatchEvent
* Consolidate state updates in Press event module
* Add keyboard support for Press events
* Add FocusProps type and unit tests
2019-04-04 08:55:35 -07:00
Dan Abramov
39da33a7bf Fix regex 2019-04-04 16:38:49 +01:00
Brian Vaughn
a9fced9b0d Prettier 2019-04-04 08:35:42 -07:00
Brian Vaughn
8c3a97401f Chagned owner div to be actual button 2019-04-04 08:35:25 -07:00
Brian Vaughn
485f389d05 Merge branch 'tab-owner' of https://github.com/gaearon/react-devtools-experimental into gaearon-tab-owner 2019-04-04 08:32:16 -07:00
Dan Abramov
8cfb0e20c7 Match search at word boundaries 2019-04-04 16:22:21 +01:00
Brian Vaughn
14969c24a9 Merge pull request #62 from gaearon/search-fix
Move selection when typing in search field
2019-04-04 08:14:57 -07:00
Dan Abramov
ec71171bec Move selection when typing in search field 2019-04-04 15:59:06 +01:00
Dan Abramov
7a2dc48539 Allow DevTools to toggle Suspense fallbacks (#15232)
* Allow DevTools to toggle Suspense state

* Change API to overrideSuspense

This lets detect support for overriding Suspense from DevTools.

* Add ConcurrentMode test

* Newlines

* Remove unnecessary change

* Naming changes
2019-04-04 15:32:32 +01:00
Dan
b1c675b8b1 Make owner stack reachable by keyboard 2019-04-04 09:56:37 +01:00
Kunuk Nykjær
e221972818 update gcc version (#15034) 2019-04-04 08:56:09 +01:00
Brian Vaughn
7fbdfd9f5a Copied findCurrentFiberUsingSlowPath Suspense bug fix from recent PR https://github.com/facebook/react/pull/15312/files 2019-04-03 18:20:18 -07:00
Brian Vaughn
99f2e0da6f Hardened background script against potential errors 2019-04-03 18:16:00 -07:00
Andrew Clark
1dcab970fa Store entire build directory as CI artifacts (#15310)
* Store FB bundles as CI artifacts

Updates the Circle CI config to store Facebook bundles as build
artifacts. We already do this for our npm packages.

* Might as well store everything in build/

* Store build directory as a tarball

So it's easy to download
2019-04-03 18:15:33 -07:00
Andrew Clark
43b1f74c88 Alternate fix for #14198
This doesn't rely on checking the tag. When the alternate of a parent
is missing, it assumes it's a fragment indirection and moves onto the
next parent fiber.
2019-04-03 15:07:09 -07:00
Brian Vaughn
ed6e34da8e Added option to disable screenshot capturing while profiling 2019-04-03 14:32:16 -07:00
Dan Abramov
41aa345d2b Fix a crash in Suspense with findDOMNode 2019-04-03 13:21:27 -07:00
Andrew Clark
6d0effad76 Expose extra internals in FB build of react-dom/unstable-new-scheduler (#15311)
The Facebook build of React DOM uses a forked entry point that exposes
additional secret internals. I didn't account for this when I added
the react-dom/unstable-new-scheduler build, so the extra internals
are currently missing. This commit adds them.
2019-04-03 12:20:42 -07:00
Brian Vaughn
07bf8e53c1 Renamed GlobalHook content script references to injectGlobalHook to avoid confusion 2019-04-03 11:01:28 -07:00
Dan Abramov
c60f991d87 Make tree reachable by focus 2019-04-03 19:01:04 +01:00
Andrew Clark
3a44ccefed Fix feature flags react-dom/unstable-new-scheduler (#15309)
I forgot to account for the CommonJS builds. (I had this change in
my local checkout but accidentally didn't commit it.)
2019-04-03 10:36:18 -07:00
Brian Vaughn
5b879ac095 Fixed a name typo in a radio button 2019-04-03 09:57:13 -07:00
Brian Vaughn
f92d2bbf83 Fixed editing props for memo and forwardRef components 2019-04-03 09:29:33 -07:00
Sunil Pai
92a1d8feac mark react-events as private so we publish script skips it for now (#15307) 2019-04-03 17:22:51 +01:00
Brian Vaughn
5bc5e31cee Merge pull request #51 from gaearon/tweak-el-display
Add a space in <Foo />
2019-04-03 09:09:11 -07:00
Dan Abramov
b2cd77d2e6 Add a space in <Foo /> 2019-04-03 17:04:31 +01:00
Brian Vaughn
6493db4acc Fixed an arrow navigation bug 2019-04-03 08:12:43 -07:00
Dan Abramov
e5c59359c4 Prevent bundling of Node polyfills when importing TestUtils/TestRenderer (#15305) 2019-04-03 16:12:31 +01:00
Brian Vaughn
6772f2a9e1 Revert fa317be (temporarily show previously selected element props) 2019-04-03 07:52:30 -07:00
Behzad Abbasi
73187239af writing unit tests in experimental event Drag API (#15297)
* writing unit tests in experimental event Drag API

* add onDragMove unit test

* fix dragstart event type
2019-04-03 12:30:57 +01:00
Dominic Gannaway
89064fe68d Adds displayName to EventComponent and EventTarget (#15268)
* Adds displayName to EventComponent and EventTarget
2019-04-03 12:24:25 +01:00
Nicolas Gallagher
fc6a9f1a1e Add test for async event dispatching (#15300)
Verified that a variant of this test fails as follows when the
`context.withAsyncDispatching` function is excluded (i.e., reproduces the
issue).

    Expected value to equal:
      ["press", "longpress", "longpresschange"]
    Received:
      ["press", "longpress", "longpress", "longpresschange"]
2019-04-03 10:43:18 +01:00
Dominic Gannaway
38fa84088a Experiemental event API - wrap async dispatched events (#15299) 2019-04-03 10:25:40 +01:00
Brian Vaughn
d1a68c4b14 Merge pull request #45 from gaearon/rename
Tab name: "Elements" -> "Components"
2019-04-02 17:55:01 -07: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
Brian Vaughn
c111288c54 Store screenshots after each commit when profiling 2019-04-02 15:04:04 -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
Sebastian Markbåge
4c75881ee3 Remove maxDuration from tests (#15272)
We instead assume a 150ms duration.
2019-04-02 14:27:44 -07:00
Dominic Gannaway
9307932fe5 Refactor event object creation for the experimental event API (#15295)
* Refactor event object creation for the experimental event API
2019-04-02 20:03:11 +01:00
Dan Abramov
83bd211c9e Elements -> Components (naming) 2019-04-02 19:58:18 +01:00
Dan Abramov
de730da230 Elements -> Components (label) 2019-04-02 19:54:22 +01:00
Brian Vaughn
f415e2447e Added missing Flow annotation 2019-04-02 11:53:18 -07: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
Brian Vaughn
fa317bed61 Merge pull request #41 from gaearon/smoother-right-pane
Avoid flashing "Loading..." in right pane
2019-04-02 10:09:43 -07:00
Nicolas Gallagher
f243deab82 Add tests for Press responder event module (#15290)
* Add Press responder event tests

Behavior being tested takes cues from React Native's Pressability.
A couple of these tests fail and require the Press implementation to be patched.
2019-04-02 16:49:41 +01:00
Nicolas Gallagher
296c4393da Add Press event prop types and fix a check in Safari (#15288)
* Add PressProps type to event module

* Move default Press event delays to constants

* Fix right-click press check for Safari

* Prettier and Linter

* Use event.key in press responder

event.keyCode is a deprecated API

* Remove unused props from Press event module
2019-04-02 14:42:37 +01:00
Brian Vaughn
b8ada905ff Merge pull request #35 from bvaughn/reload-and-profile
Eagerly inject renderer (before document) to support reload-and-profile
2019-04-01 14:47:51 -07:00
Brian Vaughn
2a80f8ca9c Show is-recording indicator earlier after a reload-and-profile 2019-04-01 14:43:46 -07:00
Brian Vaughn
f5f7cb5bdf Fixed some missing operations that could happen after reload-and-profile 2019-04-01 14:29:52 -07:00
Dominic Gannaway
4482fddeda Fix host context issues around EventComponents and EventTargets (#15284) 2019-04-01 19:33:39 +01:00
Brian Vaughn
74cd1a5d29 Misc cleanup of comments and localStorage key names 2019-04-01 09:05:40 -07:00
Behzad Abbasi
5ef0d1d29d Rename hover props in experimental event API and write unit tests (#15283)
* Rename hover props in experimental event API and write unit tests
2019-04-01 16:19:16 +01:00
Brian Vaughn
2c14f3e88e Inject early on when reloading-and-profiling 2019-04-01 07:48:14 -07:00
Dominic Gannaway
9444a54720 Warn on nested EventTragets in experimental event API (#15287) 2019-04-01 15:47:03 +01:00
Brian Vaughn
37ed5a7175 Merge pull request #38 from lucasecdb/patch-1
Fix casing on store import
2019-04-01 07:25:03 -07:00
Lucas Cordeiro
e634777027 Fix casing on store import 2019-04-01 10:25:57 -03:00
Brian Vaughn
628c1b2f08 Disable export profiling data option in Firefox. (downloads.download seems to just fail silently.) 2019-03-31 19:18:06 -07:00
Brian Vaughn
bfb152f160 Import/export feature 2019-03-31 17:02:30 -07:00
Sebastian Markbåge
a050f3d459 Delete Suspense Fixture (#15273)
As far as I can tell this build is broken. Let's fix or delete. If I can't
test, I can't patch it up when I break it.
2019-03-30 15:35:08 -07:00
Brian Vaughn
e5400f76f0 Added save profiling data button to Profiler 2019-03-30 14:16:34 -07:00
Nicolas Gallagher
7f1f5ddc33 Rename press props in experimental event API (#15263)
Note: this is for an experimental event API that we're testing out internally at Facebook.

* onPressIn -> onPressStart
* onPressOut -> onPressEnd
* longPressCancelsPress -> onLongPressShouldCancelPress
2019-03-30 16:23:41 +00:00
Brian Vaughn
7cac619c68 Added initial support for EventComponent/EventTarget 2019-03-30 09:02:02 -07:00
Brian Vaughn
7bd8c02f10 Added export and clear buttons for Profiler, cleaned up record toggle 2019-03-30 09:01:52 -07:00
Dan Abramov
b223ec3b39 Avoid flashing "Loading..." in right pane 2019-03-29 23:58:42 -07:00
Eli White
2e02469fa2 ReactNative's ref.measureLayout now takes a ref (#15126)
* ReactNative's ref.measureLayout now takes a ref

* Use Object as the additional param type

* Remove unnecessary whitespace

* Not supporting ref in mixin or subclass
2019-03-29 15:57:06 -07:00
Eli White
1b94fd215d Make setNativeProps a no-op with Fabric renderer (#15094)
* Make setNativeProps a no-op with Fabric renderer

* Remove unnecessary __DEV__ check
2019-03-29 15:44:15 -07:00
Nicolas Gallagher
08055a625e Fix Press module in experimental event API (#15262)
Note: this is for an experimental event API that we're testing out internally at Facebook.

Fixes a regression in f4625f5182
2019-03-29 14:26:55 -07:00
Nicolas Gallagher
f4625f5182 Fix on(Long)PressChange events in experimental press event API (#15256)
Make sure that `onPressChange` is only called if `longPressCancelsPress` is `false`.
And make sure that `onLongPressChange` is called when a long press ends.
2019-03-29 11:58:29 -07:00
Dominic Gannaway
a41b217708 Add additional event API responder surfaces (#15248)
* Add rest of event modules + small fixes
2019-03-29 10:31:18 -07:00
Brian Vaughn
a450a23e31 Improved Profiler suspense boundary UI 2019-03-29 08:53:39 -07:00
Nicolas Gallagher
700f17be67 Fix longpress in experimental Press event module (#15246)
The 'longpress' event is dispatched during a press interaction, rather than
after it has ended.

The 'longPressCancelsPress' prop can be used to prevent 'press' being
dispatched if 'longpress' has already been dispatched.
2019-03-28 21:44:28 -07:00
Dominic Gannaway
5d336df706 Allow for null targetFiber for root event handling (#15247) 2019-03-28 21:43:19 -07:00
Dominic Gannaway
c6f3524df5 Adds React event component and React event target support to SSR renderer (#15242)
* Adds React event component and React event target support to SSR renderer
2019-03-28 15:36:21 -07:00
Sebastian Markbåge
c7a2dce50a Disable JS urls at build level for www (#15230)
This will be on by default in open source for the next major.
2019-03-28 14:36:36 -07:00
Dan Abramov
fb6b50871b Update versions for 16.8.6 2019-03-27 23:58:16 -07:00
Dan Abramov
4148b0511d Changelog 2019-03-27 23:58:06 -07:00
Dominic Gannaway
1cfd256685 Fix circular module imports causing file size increase (#15231)
* Fix circular module imports causing file size increase
2019-03-27 21:17:58 -07:00
Dominic Gannaway
669cafb36f Adds experimental event component responder surfaces (#15228)
* Adds Press and Hover event modules + more features to the Event Responder System
2019-03-27 16:42:17 -07:00
Brian Vaughn
d8cb10f11f Enabled warnAboutDeprecatedLifecycles flag by default (#15186) 2019-03-27 16:30:49 -07:00
Brian Vaughn
61a251f01a Disable reload-and-profile button if no renderers support profiling 2019-03-27 09:50:19 -07:00
Brian Vaughn
7d24e83989 Implemented reload-and-profile. Also fixed an couple of minor profiling bugs along the way 2019-03-27 09:41:12 -07:00
Dominic Gannaway
80f8b0d512 Add part of the event responder system for experimental event API (#15179)
* Add part of the event responder system
2019-03-26 16:55:25 -07:00
Dan Abramov
d03ac4b231 Fix tracing fixture 2019-03-26 13:59:32 -07:00
Brian Vaughn
ea5f310fe1 Webpack config injects a __DEV_ constant 2019-03-26 13:22:55 -07:00
Brian Vaughn
0d5e4c7e09 Remove coverage badge from README (#15216) 2019-03-26 12:37:05 -07:00
Brian Vaughn
691068b0a3 Suppress horizontal scroll bars in snapshot selector 2019-03-26 11:23:19 -07:00
Brian Vaughn
894990919c Fixed a tab restoration bug in browser extension 2019-03-26 11:13:40 -07:00
Brian Vaughn
3fa951d3c3 Cleaned up a no-selection state 2019-03-25 10:34:22 -07:00
Brian Vaughn
030914fdca Moved some shared CSS vars into CSS 2019-03-25 10:29:25 -07:00
Brian Vaughn
3ba64e5955 Cleaned up edge cases around filtered commits 2019-03-25 10:18:38 -07:00
Brian Vaughn
5718eaf0f3 Added arrow key navigation for commits and interactions 2019-03-24 18:53:59 -07:00
Brian Vaughn
d973452c36 Removed some outdated TODO comments 2019-03-24 10:14:28 -07:00
Brian Vaughn
9d942b486a Show commit boxes in interaxctions sidebar 2019-03-24 09:58:56 -07:00
Brian Vaughn
afba752034 Clicking commits and interactions link to each other 2019-03-24 09:46:54 -07:00
Brian Vaughn
5602fc5371 Added interaction tracing test harness to shell 2019-03-24 09:21:37 -07:00
Brian Vaughn
69cdd38c9d Interaction chart with commit blocks rendering 2019-03-24 09:07:00 -07:00
Dan Abramov
5c2b2c0852 Warn about async infinite useEffect loop (#15180)
* Warn about async infinite useEffect loop

* Make tests sync
2019-03-22 20:04:34 +00:00
Dan Abramov
8e9a013c07 Release 16.8.5 2019-03-22 16:47:59 +00:00
Dan Abramov
db96d637d8 Changelog 2019-03-22 16:47:54 +00:00
Dan Abramov
8127a57c44 Update CHANGELOG.md 2019-03-22 16:47:44 +00:00
Dan Abramov
bfb5a0cfef Add 16.8.5 changelog 2019-03-22 16:47:39 +00:00
Dan Abramov
f33e5790b8 eslint-plugin-react-hooks@1.6.0 2019-03-22 13:56:07 +00:00
Dan Abramov
b1cccd1ed1 Warn about setState directly in dep-less useEffect (#15184) 2019-03-22 13:41:10 +00:00
Dominic Gannaway
78f2775ed0 Flip event passive logic on passiveBrowserEventsSupported (#15190) 2019-03-22 10:28:03 +00:00
Brian Vaughn
f161ee2eb7 React.warn() and React.error() (#15170) 2019-03-21 14:44:08 -07:00
Dan Abramov
78968bb3d9 Validate useEffect without deps too (#15183) 2019-03-21 20:42:13 +00:00
Sebastian Markbåge
4b8e1641b7 Fork performWork instead of using boolean flag (#15169)
I inline it into performAsyncWork instead.

Code that was only relevant to the async callback had leaked into the
performWork call which is an indication that this was a bad abstraction
and therefore the wrong place to DRY.

By inlining I also discovered that minExpirationTime is actually irrelevant
in the yieldy case so we can clean that up.
2019-03-21 13:20:52 -07:00
Brian Vaughn
56035dac64 unstable_Profiler -> Profiler (#15172) 2019-03-21 09:18:34 -07:00
Dan Abramov
31518135c2 Strengthen nested update counter test coverage (#15166)
* Isolate ReactUpdates-test cases

This ensures their behavior is consistent when run in isolation, and that they actually test the cases they're describing.

* Add coverage for cases where we reset nestedUpdateCounter

These cases explicitly verify that we reset the counter in right places.

* Add a mutually recursive test case

* Add test coverage for useLayoutEffect loop
2019-03-21 14:52:51 +00:00
Dominic Gannaway
66f280c87b Add internal logic for listening to event responders (#15168)
* Add the logic for listening to event responders
2019-03-21 12:32:40 +00:00
Andrew Clark
b1a56abd6a Fork ReactFiberScheduler with feature flag
Adds a feature flag `enableNewScheduler` that toggles between two
implementations of ReactFiberScheduler. This will let us land changes in
master while preserving the ability to quickly rollback.

Ideally this will be a short-lived fork. Once we've tested the new
scheduler for a week or so without issues, we will get rid of it. Until
then, we'll need to maintain two parallel implementations and run tests
against both of them. We rarely land changes to ReactFiberScheduler, so
I don't expect this will be a huge burden.

This commit does not implement anything new. The flag is still off and
tests run against the existing implementation.

Use `yarn test-new-scheduler` to run tests against the new one.
2019-03-20 16:28:33 -07:00
Andrew Clark
45f571736c ReactFiberScheduler -> ReactFiberScheduler.old
Doing this in its own commit so history and blame are preserved.
2019-03-20 16:27:59 -07:00
Brian Vaughn
64e355bb74 Added basic Interactions view (without graph for now) 2019-03-20 11:12:46 -07:00
Brian Vaughn
17a966651c Added suspense to TODO list and added interactions to 'Commit Info' panel 2019-03-20 09:39:14 -07:00
Dan Abramov
c05b4b81f9 Link to useLayoutEffect gist in a warning (#15158) 2019-03-20 13:40:36 +00:00
Renan Valentin
061d6ce3c0 fix(react-dom): access iframe contentWindow instead of contentDocument (#15099)
MDN has a list of methods for obtaining the window reference of an
iframe:

https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Syntax

fix(react-dom): check if iframe belongs to the same origin

Accessing the contentDocument of a HTMLIframeElement can cause the browser
to throw, e.g. if it has a cross-origin src attribute.
Safari will show an error in the console when the access results in "Blocked a frame with origin". e.g:

```javascript
try {
 $0.contentDocument.defaultView
} catch (err) {
  console.log('err', err)
}

> Blocked a frame with origin X from accessing a frame with origin Y. Protocols, domains, and ports must match.
> err – TypeError: null is not an object (evaluating '$0.contentDocument.defaultView')
```

A safety way is to access one of the cross origin properties: Window or Location
Which might result in "SecurityError" DOM Exception and it is compatible to Safari.

```javascript
try {
 $0.contentWindow.location.href
} catch (err) {
 console.log('err', err)
}

> err – SecurityError: Blocked a frame with origin "http://localhost:3001" from accessing a cross-origin frame. Protocols, domains, and ports must match.
```

https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl
2019-03-20 13:11:54 +00: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
Brian Vaughn
3e82e4152e Added getInteractions message 2019-03-19 18:13:44 -07:00
Dominic Gannaway
daeda44d8f Follow up to 15150 (#15152) 2019-03-19 20:55:04 +00:00
Sebastian Markbåge
acd65db5bc Deprecate module pattern (factory) components (#15145) 2019-03-19 12:55:27 -07:00
Brian Vaughn
433b6aadd6 Added placeholder Profiler sidebar views 2019-03-19 12:41:49 -07:00
Brian Vaughn
ac1a986ace Handle RTE in profiler when commit does not contain selected node 2019-03-19 11:19:30 -07:00
Brian Vaughn
1846d4fe59 Fixed a bug where treeBaseDurations were undefined for fibers that were unmounted during profiling 2019-03-19 11:08:51 -07:00
Dominic Gannaway
55cc921c5d Adds react-events package for internal testing (#15150)
* Adds react-events package for internal testing
2019-03-19 15:12:45 +00:00
Dan Abramov
7ad7386308 Improve warning for invalid class contextType (#15142)
* Improve warning for invalid class contextType

* Don't warn for null

* Grammar
2019-03-19 13:31:26 +00:00
Sebastian Markbåge
1e3364e764 Test that we don't suspend when disabling yielding (#15143) 2019-03-18 15:21:49 -07:00
Brian Vaughn
2fc03eb151 Fixed keyboard/mouse events inside of extension by using ref.ownerDocument 2019-03-18 15:11:41 -07:00
Andrew Clark
42c3c967d1 Compile invariant directly to throw expressions (#15071)
* Transform invariant to custom error type

This transforms calls to the invariant module:

```js
invariant(condition, 'A %s message that contains %s', adj, noun);
```

Into throw statements:

```js
if (!condition) {
  if (__DEV__) {
    throw ReactError(`A ${adj} message that contains ${noun}`);
  } else {
    throw ReactErrorProd(ERR_CODE, adj, noun);
  }
}
```

The only thing ReactError does is return an error whose name is set
to "Invariant Violation" to match the existing behavior.

ReactErrorProd is a special version used in production that throws
a minified error code, with a link to see to expanded form. This
replaces the reactProdInvariant module.

As a next step, I would like to replace our use of the invariant module
for user facing errors by transforming normal Error constructors to
ReactError and ReactErrorProd. (We can continue using invariant for
internal React errors that are meant to be unreachable, which was the
original purpose of invariant.)

* Use numbers instead of strings for error codes

* Use arguments instead of an array

I wasn't sure about this part so I asked Sebastian, and his rationale
was that using arguments will make ReactErrorProd slightly slower, but
using an array will likely make all the functions that throw slightly
slower to compile, so it's hard to say which way is better. But since
ReactErrorProd is in an error path, and fewer bytes is generally better,
no array is good.

* Casing nit
2019-03-18 13:58:03 -07:00
Brian Vaughn
b64a76e6bd Reset selected commit and fiber between profiling sessions 2019-03-18 13:53:10 -07:00
Brian Vaughn
9b6ee0bb22 Merge pull request #33 from bvaughn/portals
Experimenting with portals [WIP]
2019-03-18 13:37:56 -07:00
Brian Vaughn
5f154b376e Added profiling-not-supported message for browser extension 2019-03-18 13:37:37 -07:00
Brandon Dail
df7b87d25e Warn for Context.Consumer with contextType (#14831) 2019-03-18 19:27:05 +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
Brian Vaughn
be48150fc6 innerTagName -> innerElementType 2019-03-18 10:09:09 -07:00
Brian Vaughn
50b6b1d5f9 Added some inline comments about portal props 2019-03-18 09:57:08 -07:00
Brian Vaughn
e728ebc7b9 Unmount and remount when main URL changes to avoid staleness problems 2019-03-18 09:36:47 -07:00
Brian Vaughn
c9920f0954 Added a few inline comments 2019-03-18 09:20:00 -07:00
Brian Vaughn
2664036dbe Tweaked profiling did-not-render color to be dimmer 2019-03-18 09:18:22 -07:00
Brian Vaughn
11573bf8d9 Refactored portaling and fixed disconnected CSS vars 2019-03-18 09:11:28 -07:00
Brian Vaughn
f3f4643a3a Experimenting with portals 2019-03-17 13:52:37 -07:00
Brian Vaughn
d3ee02cd35 Added "Profiler" tab 2019-03-17 10:58:20 -07:00
Brian Vaughn
d685efd72f Fixed mutation bug in CommitTreeBuilder 2019-03-17 10:25:40 -07:00
Brian Vaughn
c82a7fb560 First pass at flame graph chart 2019-03-17 09:49:10 -07:00
Brian Vaughn
01ad9f1da6 Implemented ranked chart 2019-03-16 14:06:41 -07:00
Brian Vaughn
734e4146e7 Added Ranked chart data generation; fixed some logic errors in backend tree base duration tracking 2019-03-16 10:52:08 -07:00
Brian Vaughn
a93dab7f83 Reset commit tree cache between profiles 2019-03-16 08:50:28 -07:00
Brian Vaughn
821a6504b8 Added commit tree reconstruction 2019-03-15 20:05:52 -07:00
Andrew Clark
d926936f0b Eager bailout optimization should always compare to latest reducer (#15124)
* Eager bailout optimization should always compare to latest reducer

* queue.eagerReducer -> queue.lastRenderedReducer

This name is a bit more descriptive.

* Add test case that uses preceding render phase update
2019-03-15 19:03:59 -07:00
Sebastian Markbåge
4162f6026c Add feature flag to disable yielding (#15119) 2019-03-15 15:54:22 -07: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
Dominic Gannaway
035e4cffbd Change passive checker to use defineProperty (#15121) 2019-03-15 22:24:25 +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
Dan Abramov
f0621fe232 Use same example code for async effect warning (#15118) 2019-03-15 19:27:55 +00:00
Kayla Ngan
ff4fb6d368 Remove facts tracker (#15111)
* Removed Travis references

* Remove used facts tracker
2019-03-15 19:25:06 +00:00
Brian Vaughn
8a7be78ed7 Finished iterating on commit selector UI for now 2019-03-15 11:51:35 -07:00
Brian Vaughn
585c1cb3d2 Refactored Profiler tree to better work with suspense 2019-03-15 10:26:21 -07:00
Brian Vaughn
e8f84dd5c4 Iterating on Profiling tab suspense. Stashing changes but planning to refactor immediately. 2019-03-15 08:34:08 -07: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
Dan Abramov
f1ff4348c1 Don't suggest a function as its own dep (#15115) 2019-03-15 15:14:01 +00:00
Dominic Gannaway
371bbf36bb Add infrastructure for passive/non-passive event support for future API exploration (#15036)
* Add infrastructure for passive/non-passive event support for future event API experimentation
2019-03-15 09:39:43 +00:00
Mateusz
ab5fe174c6 Don't set the first option as selected in select tag with size attribute (#14242)
* Set 'size' attribute to select tag if it occurs before appending options

* Add comment about why size is assigned on select create. Tests

I added some more clarification for why size must be set on select
element creation:

- In the source code
- In the DOM test fixture
- In a unit test

* Use let, not const in select tag stub assignment
2019-03-14 14:40:09 -07:00
Dan Abramov
935f60083f eslint-plugin-react-hooks@1.5.1 2019-03-14 20:11:22 +00:00
Dominic Gannaway
0c03a47436 Adds experimental event API scaffolding (#15108)
* Adds experimental event API scaffolding
2019-03-14 17:02:42 +00:00
Brian Vaughn
210c2371cf Naive pass at commit durationfiltering 2019-03-13 17:00:44 -07:00
Brian Vaughn
8b3546b437 Profiler CSS/layout tweaks 2019-03-13 16:25:29 -07:00
Nathan Hunzaker
679402a66b Improve hydration fixture, support older versions of React (#14118)
* Hydration Fixture: Only load ReactDOMServer if it exists

Fixes an issue where the hydration fixture would try to load in
ReactDOMServer below version 14. In version 13, string markup methods
exist on the React namespace.

* DOM Fixtures: Use class component for App.js

This was breaking React 0.13.0.

* Hydration Fixture: better findDOMNode compatibility

This commit fixes an issue where the Hydration DOM fixture was
unusable in React 0.13.0 or lower because of newer API usage.

It fixes that by avoiding the use of refs to get the textarea
reference in the code editor component, using various versions of
findDOMNode as required.

* Hydration Fixture: Do not show dropdown for single-line errors

If an error showed for the hydration fixture, a detail element was
used even if no additional lines could display. In that case, this
commit changes the component such that it returns a div.

* Deeper React version support for hydration fixture

This commit adds support for versions 0.4.0 of React and higher for
the hydration fixture.

The DOM test fixtures themselves do not support down to React 0.4.0,
which would be exhaustive. Instead, the Hydration fixture can pick a
version to use for its own purposes. By default, this is the version
of React used by the fixtures.

In the process of doing this, I had to make some updates to the
renderer.html document associated with the hydration fixture, and I've
added some comments to better document the history of API changes.
2019-03-13 15:12:49 -07:00
Brian Vaughn
0edf4e9dc1 Plugged react-window into commit selector 2019-03-13 14:57:52 -07:00
Sophie Alpert
1204c78977 [eslint] Wording tweaks (#15078)
* [eslint] Wording tweaks

I think these are a little clearer.

* fix tests
2019-03-13 18:31:39 +00:00
Dan Abramov
9d77a317bf Improve async useEffect warning (#15104) 2019-03-13 16:20:13 +00:00
Brian Vaughn
b8a52078c6 Added initial Suspense cache and loaded commit metadata 2019-03-12 15:50:29 -07:00
Sebastian Markbåge
103378b1ea Warn for javascript: URLs in DOM sinks (#15047)
* Prevent javascript protocol URLs

* Just warn when disableJavaScriptURLs is false

This avoids a breaking change.

* Allow framesets

* Allow <html> to be used in integration tests

Full document renders requires server rendering so the client path
just uses the hydration path in this case to simplify writing these tests.

* Detect leading and intermediate characters and test mixed case

These are considered valid javascript urls by browser so they must be
included in the filter.

This is an exact match according to the spec but maybe we should include
a super set to be safer?

* Test updates to ensure we have coverage there too

* Fix toString invocation and Flow types

Right now we invoke toString twice when we hydrate (three times
with the flag off). Ideally we should only do it once even in this case
but the code structure doesn't really allow for that right now.

* s/itRejects/itRejectsRendering

* Dedupe warning and add the unsafe URL to the warning message

* Add test that fails if g is added to the sanitizer

This only affects the prod version since the warning is deduped anyway.

* Fix prod test
2019-03-11 16:39:49 -07:00
Sebastian Markbåge
5d0c3c6c7d [Partial Hydration] Render client-only content at normal priority (#15061)
* Split props changing from permanent fallback state

These will need different logic. In this commit, no logic has changed,
only moved.

* Delete terminal fallback content in first pass

If the dehydrated suspense boundary's fallback content is terminal there
is nothing to show. We need to get actual content on the screen soon.

If we deprioritize that work to offscreen, then the timeout heuristics will
be wrong.

Therefore, if we have no current and we're already at terminal fallback
state we'll immediately schedule a deletion and upgrade to real suspense.

* Show failing case when there is another wrapper boundary

* Revert "Delete terminal fallback content in first pass"

This reverts commit ad67ba8928c23f5d9ba22d7e5c202bf27d0e49d3.

* Use the new approach of leaving work at normal pri to replace fallback
2019-03-11 13:50:19 -07:00
Brian Vaughn
e7e62acbf9 Merge pull request #32 from reznord/fix/long-props-fix
Break the text into next line for long props
2019-03-11 11:26:41 -07:00
Brian Vaughn
f5ba99e6ba Moved some things from ProfilerContext reducer into (root) Store 2019-03-11 11:26:30 -07:00
Andrew Clark
6a4a261ee8 Test suspended children are hidden before layout in persistent mode (#15030)
Refs behave differently in persistent mode, so instead of a ref, the
persistent mode version of this test asserts on the output of the
host tree.
2019-03-11 11:19:20 -07:00
Anup
896c9a79b2 Fixes #19 - Break the text into next line for long props 2019-03-11 23:37:39 +05:30
Andrew Clark
bc8bd24c14 Run persistent mode tests in CI (#15029)
* Add command to run tests in persistent mode

* Convert Suspense fuzz tester to use noop renderer

So we can run it in persistent mode, too.

* Don't mutate stateNode in appendAllChildren

We can't mutate the stateNode in appendAllChildren because the children
could be current.

This is a bit weird because now the child that we append is different
from the one on the fiber stateNode. I think this makes conceptual
sense, but I suspect this likely breaks an assumption in Fabric.

With this approach, we no longer need to clone to unhide the children,
so I removed those host config methods.

Fixes bug surfaced by fuzz tester. (The test case that failed was the
one that's already hard coded.)

* In persistent mode, disable test that reads a ref

Refs behave differently in persistent mode. I added a TODO to write
a persistent mode version of this test.

* Run persistent mode tests in CI

* test-persistent should skip files without noop

If a file doesn't reference react-noop-renderer, we shouldn't bother
running it in persistent mode, since the results will be identical to
the normal test run.

* Remove module constructor from placeholder tests

We don't need this now that we have the ability to run any test file in
either mutation or persistent mode.

* Revert "test-persistent should skip files without noop"

Seb objected to adding shelljs as a dep and I'm too lazy to worry about
Windows support so whatever I'll just revert this.

* Delete duplicate file
2019-03-11 10:56:34 -07:00
Brian Vaughn
22a3c757fb Tidied up Profiler toolbar UI 2019-03-11 09:50:20 -07:00
Brian Vaughn
e5280307c9 Added snapshot selector placeholder UI 2019-03-10 19:16:34 -07:00
Brian Vaughn
565d739569 Added commit time filter 2019-03-10 10:13:20 -07:00
Brian Vaughn
2d68007288 Initial profiling shell added
Lots of TODOs and unfinished views here.
2019-03-10 09:01:05 -07:00
Brian Vaughn
2606d119be Merge branch 'master' of github.com:bvaughn/react-devtools-experimental 2019-03-09 14:09:04 -08:00
Brian Vaughn
c687252b6a Updated Profiling overview/proposal again 2019-03-09 14:08:51 -08:00
Andrew Clark
3f4852fa5f Run Placeholder tests in persistent mode, too (#15013)
* Convert ReactSuspensePlaceholder tests to use noop

Instead of the test renderer, since test renderer does not support
running in persistent mode.

* Run Placeholder tests in persistent mode, too

* Fix Flow and lint

* Hidden text instances should have correct host context

Adds a test for a subtle edge case that only occurs in persistent mode.

* createHiddenTextInstance -> cloneHiddenTextInstance

This sidesteps the problem where createHiddenTextInstance needs access
to the host context.
2019-03-08 18:53:14 -08:00
Brian Vaughn
a5de36b0c2 Merge pull request #29 from tsriram/fix-import
Fix import file name
2019-03-08 17:41:58 -08:00
Sriram Thiagarajan
3118dae375 fix import file name 2019-03-09 07:03:42 +05:30
Brian Vaughn
5386917f59 Refined OVERVIEW a little more 2019-03-07 14:31:03 -08:00
Brian Vaughn
20b613dcde Updated Profiler OVERVIEW 2019-03-07 14:15:12 -08:00
Dan Abramov
d0289c7e3a eslint-plugin-react-hooks@1.5.0 2019-03-07 19:43:07 +00:00
Dan Abramov
03ad9c73e4 [ESLint] Tweak setState updater message and add useEffect(async) warning (#15055)
* Use first letter in setCount(c => ...) suggestion

In-person testing showed using original variable name confuses people.

* Warn about async effects
2019-03-07 19:40:23 +00:00
Dan Abramov
eb6247a9ab More concise messages (#15053) 2019-03-07 15:21:44 +00:00
Dan Abramov
197703ecc7 [ESLint] Add more hints to lint messages (#15046)
* A clearer message for props destructuring where applicable

* Add line number to the "move function" message

* Add a hint for how to fix callbacks from props

* Simplify code and harden tests

* Collect all dependency references for better warnings

* Suggest updater or reducer where appropriate
2019-03-07 12:39:15 +00:00
Brian Vaughn
0ac84f3065 Added explicit Profiler goals to OVERVIEW 2019-03-06 18:30:17 -08:00
Brian Vaughn
4257ba4983 Changed profilerSummary messages to be lazy as well 2019-03-06 18:21:38 -08:00
Brian Vaughn
181e8aff30 Added planned Profiler architecture to OVERVIEW doc to share with others 2019-03-06 18:12:11 -08:00
Dan Abramov
6d2666bab1 Fix ESLint rule crash (#15044) 2019-03-07 00:39:39 +00:00
Dan Abramov
9b7e1d1389 [ESLint] Suggest moving inside a Hook or useCallback when bare function is a dependency (#15026)
* Warn about bare function deps and suggest moving or useCallback

* Clearer wording
2019-03-06 23:50:02 +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
e9028d1d35 Re-organized views slightly in preparation for Profiler UI 2019-03-06 14:01:52 -08:00
Brian Vaughn
c18449326d Disabled transferrables for now (to avoid a Chrome runtime error) 2019-03-06 13:17:20 -08:00
Dan Abramov
5d49dafac8 Enforce deps array in useMemo and useCallback (#15025) 2019-03-06 18:17:54 +00:00
Brian Vaughn
a9aa24ed8d 16.8.4 and changelog 2019-03-05 15:17:42 -08:00
Dan Abramov
db8d466554 Fix heading in changelog 2019-03-05 22:40:04 +00:00
Dan Abramov
fa5d4ee43b [ESLint] Treat functions that don't capture anything as static (#14996)
* Treat functions that don't capture anything as static

* Fix comment
2019-03-05 21:07:37 +00:00
Dan Abramov
fd557d453d Warn on mount when deps are not an array (#15018)
* Warn on mount when deps are not an array

* Check other Hooks

* I can't figure out how to fix error/warning nesting lint

But it doesn't really matter much because we test other cases in the other test.
2019-03-05 17:41:27 +00:00
Farhad Yasir
ff596e3efb fix(auto-version-update): update root package version while publishing (#15005)
* fix(auto-version-update): update root package version while publishing

* fix(remove-version): remove version field from package json
2019-03-04 12:36:17 -08:00
Andrew Clark
ce45ca9ba3 Prettier 2019-03-04 11:38:08 -08:00
Andrew Clark
757a70b25d ReactNoop.yield -> Scheduler.yieldValue (#15008)
These used to be different things, but now ReactNoop.yield merely
re-exports Scheduler.yieldValue, so let's get rid of it.
2019-03-04 11:23:00 -08:00
Brian Vaughn
0db7770cf7 Merged master 2019-03-03 12:41:08 -08:00
Brian Vaughn
235851da87 Merge pull request #27 from gaurav5430/master
Update OVERVIEW.md
2019-03-03 08:14:05 -08:00
Gaurav Gupta
f94401c10e Update OVERVIEW.md
Fixed the superscript reference
2019-03-03 18:29:58 +05:30
Andrew Clark
9d756d903f Revert #14756 changes to ReactFiberScheduler (#14992)
* Revert #14756 changes to ReactFiberScheduler

This PR introduced some bugs in concurrent mode during internal testing.
Until we figure out a proper solution, I'm going to try reverting it.

Not totally certain this is sufficient to unbreak the bugs we found, but
I'm using this branch to determine that.

* Add back commented out Scheduler import

With a note not to use named imports next time we import Scheduler
in this module.
2019-03-01 13:10:12 -08:00
Dan Abramov
f16442a106 eslint-plugin-react-hooks@1.4.0 2019-03-01 20:29:06 +00:00
Dan Abramov
e1e45fb367 [ESLint] Suggest to destructure props when they are only used as members (#14993)
* Suggest to destructure props when they are only used as members

* Add more tests

* Fix a bug
2019-03-01 19:48:48 +00:00
Dan Abramov
59ef28437a Warn about dependencies outside of render scope (#14990) 2019-03-01 18:16:17 +00:00
Brian Vaughn
515b60cc5e Fixed a typo in OVERVIEW 2019-03-01 08:38:05 -08:00
Brian Vaughn
8aa6f96279 Fixed selecterd element background color being cut-off when tree scrolls
This required a bit of unusual CSS but seems to work well for Firefox and Chrome. We can remove it and revisit other approaches (like PR#24) in the future if needed.
2019-03-01 08:28:16 -08:00
Dan Abramov
df7b4768c7 [ESLint] Deduplicate suggested dependencies (#14982)
* Deduplicate suggested dependencies

* Tweak test cases
2019-03-01 16:10:22 +00:00
Dan Abramov
02404d793b Avoid dynamic dispatch for scheduler calls (#14968) 2019-03-01 15:04:15 +00:00
Brian Vaughn
0401f34f55 Removed unnecessary relative position style from Element CSS 2019-02-28 14:50:27 -08:00
Brian Vaughn
bb2939ccc2 Support editable useState hooks in DevTools (#14906)
* ReactDebugHooks identifies State and Reducer hooks as editable
* Inject overrideHookState() method to DevTools to support editing in DEV builds
* Added an integration test for React DevTools, react-debug-tools, and overrideHookState
2019-02-28 14:37:55 -08:00
Brian Vaughn
90001e892d Udpated param name in injected renderer overrideHookState type 2019-02-28 13:55:49 -08:00
Brian Vaughn
d70dbfdb65 Added intro to OVERVIEW 2019-02-28 13:46:36 -08:00
Brian Vaughn
c249e31932 Fixed docs typo: chlid -> child 2019-02-28 13:26:39 -08:00
Brian Vaughn
7da5f83a28 Updated to account for facebook/react/pull/14906/commits/cdd9ba4 2019-02-28 13:22:27 -08:00
Brian Vaughn
c7f8557202 Improve selected node highlighting by using minWidth instead of width 2019-02-28 12:56:49 -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
Brian Vaughn
bffa72c601 Add placeholders to clarify between empty string, null, and undefined 2019-02-28 10:46:17 -08:00
Andrew Clark
53e787b45f Replace noop's fake Scheduler implementation with mock Scheduler build (#14969)
* Replace noop's fake Scheduler implementation with mock Scheduler build

The noop 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.

Most of the existing noop tests were unaffected, but I did have to make
some changes. The biggest one involved passive effects: previously, they
were scheduled on a separate queue from the queue that handles
rendering. After this change, both rendering and effects are scheduled
in the Scheduler queue. I think this is a better approach because tests
no longer have to worry about the difference; if you call `flushAll`,
all the work is flushed, both rendering and effects. But for those few
tests that do care to flush the rendering without the effects, that's
still possible using the `yieldValue` API.

Follow-up: Do the same for test renderer.

* Fix import to scheduler/unstable_mock
2019-02-28 10:30:46 -08:00
Brian Vaughn
d34a32d389 Disable text selection in tree 2019-02-28 09:44:04 -08:00
Brian Vaughn
d6a2ba2616 Added OVERVIEW doc 2019-02-28 08:52:54 -08:00
Brian Vaughn
bcb6c2fd9f Removed an unnecessary entry from add-root operation array 2019-02-28 08:52:46 -08:00
Brian Vaughn
13ca37384d Maybe fixed checkbox alignment issue Dan reported? 2019-02-27 13:54:53 -08:00
Brian Vaughn
0153eaedee Left arrow selects parent in tree 2019-02-27 13:49:46 -08:00
Brian Vaughn
bf02b2ffbf Select DOM element mode should useCapture to prevent clicks from passing through 2019-02-27 13:33:10 -08:00
Brian Vaughn
05ef0ad7dc Disable view-source button rather than hiding it to avoid jumping when selecting new components 2019-02-27 13:30:03 -08:00
Brian Vaughn
1e4434ecc4 Changed select-on-click to select-on-mouse-down and fixed a scrollIntoView problem 2019-02-27 13:11:23 -08:00
Brian Vaughn
8041bfb92f Add .vscode to .gitignore 2019-02-27 13:07:09 -08:00
Brian Vaughn
bc4e8950f6 Updated test code to include a deeply nested DIV 2019-02-27 13:05:43 -08:00
Brian Vaughn
4d9e7e75c6 Merge branch 'scroll-into-view' of https://github.com/Jessidhia/react-devtools-experimental into Jessidhia-scroll-into-view 2019-02-27 12:58:03 -08:00
Dan Abramov
3ada82b741 Allow extraneous effect dependencies (#14967)
This makes cases like

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [activeTab]);

not warn.

However, it still warns for unused useCallback/useMemo deps.
2019-02-27 16:59:11 +00:00
Andrew Clark
00748c53e1 Add new mock build of Scheduler with flush, yield API (#14964)
* Add new mock build of Scheduler with flush, yield API

Test environments need a way to take control of the Scheduler queue and
incrementally flush work. Our current tests accomplish this either using
dynamic injection, or by using Jest's fake timers feature. Both of these
options are fragile and rely too much on implementation details.

In this new approach, we have a separate build of Scheduler that is
specifically designed for test environments. We mock the default
implementation like we would any other module; in our case, via Jest.
This special build has methods like `flushAll` and `yieldValue` that
control when work is flushed. These methods are based on equivalent
methods we've been using to write incremental React tests. Eventually
we may want to migrate the React tests to interact with the mock
Scheduler directly, instead of going through the host config like we
currently do.

For now, I'm using our custom static injection infrastructure to create
the two builds of Scheduler — a default build for DOM (which falls back
to a naive timer based implementation), and the new mock build. I did it
this way because it allows me to share most of the implementation, which
isn't specific to a host environment — e.g. everything related to the
priority queue. It may be better to duplicate the shared code instead,
especially considering that future environments (like React Native) may
have entirely forked implementations. I'd prefer to wait until the
implementation stabilizes before worrying about that, but I'm open to
changing this now if we decide it's important enough.

* Mock Scheduler in bundle tests, too

* Remove special case by making regex more restrictive
2019-02-26 20:51:17 -08:00
Brian Vaughn
4186952a6f Fixed incompatibility between react-debug-tools and useContext() (#14940)
* Refactor hook ordering check to use DEV-only data structure. This enables us to warn about more cases (e.g. useContext, useDebugValue) withou the need to add any overhead to production bundles.
2019-02-26 14:24:52 -08:00
Dan Abramov
0b8efb229c Allow omitting constant primitive deps (#14959) 2019-02-26 16:12:15 +00: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
Eli White
870214f37a Deprecate ref.setNativeProps in favor of ReactNative.setNativeProps (#14912)
* Deprecate ref.setNativeProps in favor of ReactNative.setNativeProps

* Using a feature flag for the setNativeProps warning

* Removing extra line breaks

* Set the FB native feature flag to true

* Prettier
2019-02-25 15:00:39 -08:00
Dan Abramov
3989c09500 eslint-plugin-react-hooks@1.3.0 2019-02-25 17:27:37 +00:00
Dan Abramov
1bbfbc98d2 [ESLint] Add more cases to exhaustive-deps rule (#14930)
* Add better message for literal dependencies

* Warn about ref.current in cleanup phase

* Fix wrong comment

* Tweak wording
2019-02-25 16:00:29 +00:00
Farhad Yasir
412f882968 fix(eslint-plugin-react-hooks): node engine updated to version 7 because of object.entries (#14951) 2019-02-25 15:37:06 +00:00
Brian Vaughn
89df0a6363 Yarn upgrade 2019-02-24 18:32:29 -08:00
Marco
1d6b1660a2 Fixed typo (#14943) 2019-02-24 09:50:23 -08:00
Brian Vaughn
9f24e8c7a2 Renamed overrideHook -> overrideHookState (to stay in sync with React PR) 2019-02-23 09:12:17 -08:00
Brian Vaughn
9b96b1f809 Updated deploy scripts and pre-release template 2019-02-23 08:59:21 -08:00
Andrew Clark
ba708fa79b Remove ReactNoop.flushDeferredPri and flushUnitsOfWork (#14934)
* Remove ReactNoop.flushDeferredPri and flushUnitsOfWork

Some of our older tests worked by counting how many times React checked
whether it should yield to the main thread, instead of something
publicly observable like how many times a component is rendered.

Our newer tests have converged on a style where we push into a log and
make assertions on the log. This pattern is less coupled to the
implementation while still being sufficient to test performance
optimizations, like resuming (whenever we add that back).

This commit removes flushDeferredPri and flushUnitsOfWork and upgrades
the affected tests.

* Remove shouldYieldToRenderer indirection

This wrapper is no longer necessary.
2019-02-22 17:27:30 -08:00
Andrew Clark
920b0bbb3c [scheduler] Pass didTimeout argument to callbacks (#14931)
As I prepare to refactor the Fiber scheduler, I've noticed some quirks
in our implementation. This PR addressed one of them.

---

There's no reason for a timed out Scheduler callback to check
`shouldYield`, because the value will always be false until the work
has completed. The `didTimeout` argument provides this information to
the callback so it can avoid the redundant checks.

React's existing check for whether a callback has timed out didn't make
any sense, but happened to work anyway. I don't think the wrongness of
the old implementation is observable via React APIs but it's
incoherent regardless.
2019-02-22 16:39:10 -08:00
Brian Vaughn
7b2f06e3d3 Added (temporary) deploy scripts for pre-release extensions 2019-02-22 14:36:10 -08:00
Brian Vaughn
53632883b6 Implemented view-source button for DOM extension 2019-02-22 13:24:03 -08:00
Brian Vaughn
105b53f0fb Split :active and :focus styles for Button+Toggle 2019-02-22 10:54:18 -08:00
Brian Vaughn
5fd9cb5dfb Added copy props/state/hooks/context button 2019-02-22 09:39:05 -08:00
Brian Vaughn
1edbfbf6cb Fixed some small overflow/scrollbar issues 2019-02-22 08:44:05 -08:00
Brian Vaughn
33cb3f04f1 Release script clarifies which test fixture failed (#14922) 2019-02-22 07:43:27 -08:00
Brian Vaughn
f708f9e307 Improve pactch release process docs (#14923) 2019-02-22 07:43:18 -08:00
Matt Thomson
f99fca3cb2 Fix sample ESLint configuration (#14926)
See [ESLint docs](https://eslint.org/docs/user-guide/configuring#configuring-rules)
2019-02-22 12:22:07 +00:00
Brian Vaughn
0c346ceea8 Re-added transferrables (after 'shutdown' evt fix) and guard against a tree mutation race 2019-02-21 14:56:11 -08:00
Brian Vaughn
caf2eb973a Split large InspectedElementTree file into separate component-files 2019-02-21 14:20:14 -08:00
Brian Vaughn
9898db02d1 Restore input focus after clicking reset value button 2019-02-21 14:13:48 -08:00
Brian Vaughn
4f64c9ef9e Tweaked colors; Esc key to undo edits 2019-02-21 14:11:06 -08:00
Brian Vaughn
ddeb78001c Tweaked colors based on Andrew's feedback 2019-02-21 14:02:45 -08:00
Brian Vaughn
290e8c6926 Fixed null input value. Tweaked useReducer test harness. 2019-02-21 13:40:23 -08:00
Brian Vaughn
bdf8065137 Merge branch 'master' of github.com:bvaughn/react-devtools-experimental 2019-02-21 13:24:15 -08:00
Brian Vaughn
6f118497e8 Updated editable hooks UI and added limited undo feature 2019-02-21 13:24:01 -08:00
Brian Vaughn
2b27f63a61 Updated ESLint hooks rule 2019-02-21 11:55:28 -08:00
Dan Abramov
22bb947642 Release eslint-plugin-react-hooks@1.2.0 2019-02-21 19:41:35 +00:00
Dan Abramov
a77bbf1a1c [ESLint] Warn against assignments from inside Hooks (#14916)
* [ESLint] Warn against assignments from inside Hooks

* Include variable name

* Add a test for the legit case
2019-02-21 19:23:00 +00:00
Dan Abramov
219ce8a9cc Fix tracing fixture (#14917) 2019-02-21 18:14:32 +00:00
Dan Abramov
8c1966590a Release 16.8.3 2019-02-21 18:09:18 +00:00
Dan Abramov
7de4d23919 Fix UMD builds by re-exporting the scheduler priorities (#14914) 2019-02-21 17:20:28 +00:00
Brian Vaughn
df4a09d9b8 Updated flow-bin from 91 -> 93 and removed unnecessary fixmes 2019-02-21 09:15:47 -08:00
Brian Vaughn
e35819e68d Renamed nativeHookIndex -> index 2019-02-21 08:59:46 -08:00
Nathan Hunzaker
d0318fb3f9 Updating copyright headers, dropping the year (#14893)
* Updating copyright headers, dropping the year
* Update copyright in ReactDOMHooks-test and react-cache LRU.js
2019-02-21 08:46:13 -08:00
Brian Vaughn
532cca8013 Merge pull request #4 from mishaor/linux-support
Added support for Linux
2019-02-21 08:24:33 -08:00
Michael Orishich
b0ccd9d89e added basic support for Linux 2019-02-21 20:00:11 +02:00
Eli White
f978d5fde4 Fix warning message for new setNativeProps method. on -> with (#14909) 2019-02-20 23:53:21 -08:00
Eli White
b0f45c0fc6 Adding ReactNative.setNativeProps that takes a ref (#14907)
* Adding ReactNative.setNativeProps that takes a ref

* Adding test for components rendered with Fabric with Paper's setNativeProps

* Fixing flow types

* Fix prettier

* Rename ReactNativeSetNativeProps.js to be more general
2019-02-20 23:20:42 -08:00
Brian Vaughn
8cd8b29015 Added support for editable hook values (pending facebook/react/pull/14906) 2019-02-20 15:58:52 -08:00
Brian Vaughn
90f98372a9 Fixed broken 'shutdown' event that lead to CPU problems when reloading DevTools 2019-02-20 11:55:48 -08:00
Brian Vaughn
42795b22bf Installed eslint-plugin-react-hooks@next and added to ESLint config 2019-02-20 11:03:50 -08:00
Brian Vaughn
bec073365d Fix hooks warnings identified by prerelease version of react-hooks ESLint plugin 2019-02-19 13:15:57 -08:00
Brian Vaughn
a31415011d Removed numeric key code 2019-02-19 08:59:27 -08:00
Brian Vaughn
3376daaa41 Merge pull request #2 from Jessidhia/fix-utf-encoding
Fix encoding of Unicode keys greater than U+00FF
2019-02-19 08:56:21 -08:00
Jessica
044e6ba9cd Pass options to scrollIntoView 2019-02-19 16:36:43 +09:00
Jessica
65d493cae9 Just use codepoints as it'll be copied into an Uint32Array anyway 2019-02-19 16:03:53 +09:00
Jessica
4ee74f7e6c Fix encoding of Unicode keys greater than U+00FF (greater than U+FFFF handled by surrogate pairs) 2019-02-19 15:52:24 +09:00
Jessica
28ea0a352e Scroll to newly selected component if it's out of view 2019-02-19 12:22:19 +09:00
Brian Vaughn
a4212dcdce Support editable props, state, and context values 2019-02-17 13:07:39 -08:00
Brian Vaughn
6c226b0c80 Added link to now.sh preview to README 2019-02-16 09:46:10 -08:00
Brian Vaughn
c4d6fdbfdb Fixed overlay position bug 2019-02-16 08:33:38 -08:00
Brian Vaughn
1d95098177 Implemented select-DOM-element button 2019-02-16 08:29:26 -08:00
Brian Vaughn
2fbacbff01 Tab bar resizes properly for narrow screens 2019-02-15 11:42:55 -08:00
Brian Vaughn
0008bb00d7 Inspectable complex hook values 2019-02-14 21:55:09 -08:00
Brian Vaughn
47a5fd59cb Reduced tree padding (left) slightly to make larger trees easier to inspect 2019-02-14 15:13:43 -08:00
Brian Vaughn
04a0d24f0f Fixed a potential source of duplicate key 2019-02-14 15:06:38 -08:00
Brian Vaughn
3f40d38203 Fixed edge case mutation bugs in selected element and tree context 2019-02-14 14:36:29 -08:00
Brian Vaughn
bf2f13d32a Removed some stale TODO comments 2019-02-14 13:37:40 -08:00
Brian Vaughn
9cfa25bdcc Tidied up Flow types for Bridge and Store 2019-02-14 13:32:30 -08:00
Brian Vaughn
b167dd339b Style, theme, and button CSS cleanup 2019-02-14 13:20:24 -08:00
Brian Vaughn
a07d9862ca Fixed edge-case display density bug 2019-02-14 12:46:27 -08:00
Brian Vaughn
15c5396169 Re-added "Settings" panel to browser extension and (hopefully) fixed a lot of sources of error 2019-02-14 11:45:11 -08:00
Brian Vaughn
5a301cd26e Tweaked the owner stack exit icon 2019-02-14 09:23:54 -08:00
Brian Vaughn
36e596ecd1 Changed dark theme to have more React blues 2019-02-14 09:17:29 -08:00
Brian Vaughn
94aab74253 Avoid NPE in Agent if renderer can't be found for an ID 2019-02-14 08:13:35 -08:00
Brian Vaughn
c229837f33 Temporarily disabled Settings panel 2019-02-13 11:36:43 -08:00
Brian Vaughn
79f57532b9 Split demo app into multiple roots and fixed a multi-root bug 2019-02-13 11:22:22 -08:00
Brian Vaughn
4ea81337f3 Initial pass at adding Settings panel to browser extension 2019-02-13 10:59:49 -05:00
Brian Vaughn
aed1713154 Added NOW config file for dev shell 2019-02-12 21:09:50 -05:00
Brian Vaughn
95b859209f Fixed NaN warning for pre-mount CSS prop read 2019-02-12 21:09:33 -05:00
Brian Vaughn
d203ebf165 Added new tabs UI and theme/display-density preferences 2019-02-12 20:41:39 -05:00
Brian Vaughn
8e5a35b762 Misc cleanup and prep for dark mode CSS 2019-02-12 09:45:00 -05:00
Brian Vaughn
f3f497f40f Cleaned up CSS vars and reduced font size a bit 2019-02-08 20:27:10 -05:00
Brian Vaughn
a6126c9e27 Initial stab at 'View in DOM' button 2019-02-08 18:48:29 -05:00
Brian Vaughn
baa6142801 Removed non-functioning tree arrows (for now) 2019-02-08 16:16:15 -05:00
Brian Vaughn
c6b0338f13 Reverted immutable element change (for now) 2019-02-08 16:05:48 -05:00
Brian Vaughn
872d0f78d4 Tweaked owners breadcrumb style to batter match tree colors 2019-02-08 15:49:52 -05:00
Brian Vaughn
41514d67f0 Small refinements to Store: read-only Elements in map, added revision to guard against tearing 2019-02-08 15:37:52 -05:00
Brian Vaughn
0380186501 Refactored tree, search, selection, and owners contexts 2019-02-08 14:44:07 -05:00
Brian Vaughn
45641e98e5 Added owner tree exploration view 2019-02-07 14:34:24 +00:00
Brian Vaughn
fc924d136a Combined search and selection contexts to avoid complicated dependencies 2019-02-07 09:29:42 +00:00
Brian Vaughn
9c093ac731 Fixed regexp parsing 2019-02-06 21:33:44 +00:00
Brian Vaughn
c61e0f0d54 Added a clarifying comment to SearchInput 2019-02-06 17:09:46 +00:00
Brian Vaughn
e77ba00336 Replaced SearchContext useStates with useReducer and fixed an edge-case search bug 2019-02-06 16:31:02 +00:00
Brian Vaughn
998e69a10d Added search support 2019-02-05 17:14:06 +00:00
Brian Vaughn
e723ec82bc Added $r support 2019-02-05 13:19:08 +00:00
Brian Vaughn
ce7f060e26 Cleaned up property borders 2019-02-05 11:26:37 +00:00
Brian Vaughn
6dc3fa6fbd Cleaned up style vars 2019-02-05 11:23:37 +00:00
Brian Vaughn
1566141177 Strip React elements from serialized data (and display <name/> instead 2019-02-05 10:25:33 +00:00
Brian Vaughn
33deb79ce4 Added simple hooks support (same as in legacy DevTools for now)
I had to add a couple of  comments because Flow was being a mysterious little shit and I got tired of trying to work around it.
2019-02-05 09:23:14 +00:00
Brian Vaughn
d0d5b677de Added better context support 2019-02-05 08:32:02 +00:00
Brian Vaughn
6f952ede2f Fixed regression in browser shell 2019-02-04 18:01:44 +00:00
Brian Vaughn
b56bc1a626 Initial pass at properties panel. Lots of TODOs remaining. 2019-02-04 17:49:30 +00:00
Brian Vaughn
406df2a617 Added properties panel and selected element context 2019-02-02 13:57:32 -08:00
Brian Vaughn
9aa6e13d5f Tidied up devtools frontend a little 2019-02-01 09:25:54 -08:00
Brian Vaughn
ad74c54670 Adding tearing warning to Store 2019-01-31 15:59:08 -08:00
Brian Vaughn
1866aef67c Fixed small CSS bug 2019-01-31 15:48:47 -08:00
Brian Vaughn
1eccdd6f8a Moved search icon into separate React component 2019-01-31 14:46:18 -08:00
Brian Vaughn
89f4955b93 Don't show roots in Elements tree 2019-01-31 14:31:12 -08:00
Brian Vaughn
bdfaeede6d Fixed potential race cases in bridge/store/backend initialization 2019-01-31 14:27:16 -08:00
Brian Vaughn
62f8c985df Added stub search row (not connected to anythign yet) 2019-01-31 09:42:07 -08:00
Brian Vaughn
6363fc0767 Tweaked error message to provide more helpful info if shown 2019-01-30 14:39:37 -08:00
Brian Vaughn
ca6151ca01 Reload extension on navigate 2019-01-30 14:16:55 -08:00
Brian Vaughn
6d37857df3 Fixed an Array type bug in Store 2019-01-30 11:31:13 -08:00
Brian Vaughn
a60c8e139a Renamed app.js to App.js for consistency 2019-01-30 10:49:50 -08:00
Brian Vaughn
037071c0e1 Remove root from "roots" list on unmount 2019-01-30 10:41:53 -08:00
Brian Vaughn
1f46df66cb Tidying up 2019-01-30 10:38:52 -08:00
Brian Vaughn
f542f879d6 Added inline comments for types 2019-01-29 14:04:00 -08:00
Brian Vaughn
fc4af4d018 Fixed text wrap bug in extension panel 2019-01-29 13:48:35 -08:00
Brian Vaughn
fdfadef928 Refactored bridge to support transferrables (e.g. typed array buffers) and added transferable param to postMessage for op codes 2019-01-29 13:17:37 -08:00
Brian Vaughn
3f93b029a4 Replaced node objects with typed array of tree operations; windowing works in small test harness 2019-01-28 15:50:48 -08:00
Brian Vaughn
c9a5f8cc29 Stashing partial windowing implementation 2019-01-27 16:04:17 -08:00
Brian Vaughn
b7cbd38214 Misc updates to better handle tearing and add some future TODOs 2019-01-27 07:58:09 -08:00
Brian Vaughn
13ca26e153 Removed throttling. It's too error prone because of mutations (Fibers). We'll optimize later by using the effects list for updates. 2019-01-24 13:45:29 -08:00
Brian Vaughn
d57ec69561 Added initial Chrome/Firefox shells 2019-01-23 18:06:21 -08:00
Brian Vaughn
f881c32304 Added Prettier (and formatted code) 2019-01-23 08:45:19 -08:00
Brian Vaughn
d02b4a2784 Throttle bridge traffic for Elements tree updates 2019-01-23 08:27:40 -08:00
Brian Vaughn
7b9a8e9843 Added a super basic README 2019-01-22 11:07:56 -08:00
Brian Vaughn
5e0dfdac54 Initial commit 2019-01-22 11:04:37 -08:00
1021 changed files with 147105 additions and 29572 deletions

View File

@@ -1,23 +0,0 @@
{
"presets": ["react"],
"ignore": ["third_party"],
"plugins": [
"transform-class-properties",
"syntax-trailing-function-commas",
["transform-object-rest-spread", { "useBuiltIns": true }],
"transform-es2015-template-literals",
"transform-es2015-literals",
"transform-es2015-arrow-functions",
"transform-es2015-block-scoped-functions",
["transform-es2015-classes", { "loose": true }],
"transform-es2015-object-super",
"transform-es2015-shorthand-properties",
"transform-es2015-computed-properties",
"transform-es2015-for-of",
"check-es2015-constants",
["transform-es2015-spread", { "loose": true }],
"transform-es2015-parameters",
["transform-es2015-destructuring", { "loose": true }],
["transform-es2015-block-scoping", { "throwIfClosureRequired": true }]
]
}

View File

@@ -1,48 +1,422 @@
version: 2
aliases:
- &docker
- image: circleci/openjdk:8-jdk-node-browsers
- &environment
TZ: /usr/share/zoneinfo/America/Los_Angeles
- &restore_yarn_cache
restore_cache:
name: Restore node_modules cache
keys:
- v1-node-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
- v1-node-{{ arch }}-{{ .Branch }}-
- v1-node-{{ arch }}-
- &run_yarn
run:
name: Install Packages
command: yarn --frozen-lockfile
- &attach_workspace
at: build
- &process_artifacts
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- *run_yarn
- run: node ./scripts/rollup/consolidateBundleSizes.js
- run: ./scripts/circleci/upload_build.sh
- run: ./scripts/circleci/pack_and_store_artifact.sh
- store_artifacts:
path: ./node_modules.tgz
- store_artifacts:
path: ./build.tgz
- store_artifacts:
path: ./build/bundle-sizes.json
- store_artifacts:
# TODO: Update release script to use local file instead of pulling
# from artifacts.
path: ./scripts/error-codes/codes.json
- persist_to_workspace:
root: build
paths:
- bundle-sizes.json
jobs:
build:
docker:
- image: circleci/openjdk:8-jdk-node-browsers
environment:
TZ: /usr/share/zoneinfo/America/Los_Angeles
TRAVIS_REPO_SLUG: facebook/react
parallelism: 4
setup:
docker: *docker
environment: *environment
steps:
- checkout
- run: echo $CIRCLE_COMPARE_URL | cut -d/ -f7
- restore_cache:
name: Restore node_modules cache
keys:
- v1-node-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
- v1-node-{{ arch }}-{{ .Branch }}-
- v1-node-{{ arch }}-
- run:
name: Nodejs Version
command: node --version
- run:
name: Install Packages
command: yarn install --frozen-lockfile
- run:
name: Test Packages
command: ./scripts/circleci/test_entry_point.sh
- *restore_yarn_cache
- *run_yarn
- save_cache:
name: Save node_modules cache
key: v1-node-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
lint:
docker: *docker
environment: *environment
steps:
- checkout
- *restore_yarn_cache
- *run_yarn
- run: node ./scripts/prettier/index
- run: node ./scripts/tasks/eslint
- run: ./scripts/circleci/check_license.sh
- run: ./scripts/circleci/check_modules.sh
- run: ./scripts/circleci/test_print_warnings.sh
flow:
docker: *docker
environment: *environment
steps:
- checkout
- *restore_yarn_cache
- *run_yarn
- run: node ./scripts/tasks/flow-ci
test_source:
docker: *docker
environment: *environment
steps:
- checkout
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: stable
command: yarn test --maxWorkers=2
test_source_experimental:
docker: *docker
environment: *environment
steps:
- checkout
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: experimental
command: yarn test --maxWorkers=2
test_source_persistent:
docker: *docker
environment: *environment
steps:
- checkout
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: stable
command: yarn test-persistent --maxWorkers=2
test_source_prod:
docker: *docker
environment: *environment
steps:
- checkout
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: stable
command: yarn test-prod --maxWorkers=2
build:
docker: *docker
environment: *environment
parallelism: 20
steps:
- checkout
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: stable
command: |
./scripts/circleci/add_build_info_json.sh
./scripts/circleci/update_package_versions.sh
yarn build
- run: echo "stable" >> build/RELEASE_CHANNEL
- persist_to_workspace:
root: build
paths:
- RELEASE_CHANNEL
- facebook-www
- node_modules
- react-native
- dist
- sizes/*.json
- store_artifacts:
path: ./node_modules.tgz
build_experimental:
docker: *docker
environment: *environment
parallelism: 20
steps:
- checkout
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: experimental
command: |
./scripts/circleci/add_build_info_json.sh
./scripts/circleci/update_package_versions.sh
yarn build
- run: echo "experimental" >> build/RELEASE_CHANNEL
- persist_to_workspace:
root: build
paths:
- RELEASE_CHANNEL
- facebook-www
- node_modules
- react-native
- dist
- sizes/*.json
- store_artifacts:
path: ./scripts/error-codes/codes.json
# These jobs are named differently so we can distinguish the stable and
# and experimental artifacts
process_artifacts: *process_artifacts
process_artifacts_experimental: *process_artifacts
sizebot:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- *run_yarn
# This runs in the process_artifacts job, too, but it's faster to run
# this step in both jobs instead of running the jobs sequentially
- run: node ./scripts/rollup/consolidateBundleSizes.js
- run:
environment:
RELEASE_CHANNEL: stable
command: node ./scripts/tasks/danger
sizebot_experimental:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- *run_yarn
# This runs in the process_artifacts job, too, but it's faster to run
# this step in both jobs instead of running the jobs sequentially
- run: node ./scripts/rollup/consolidateBundleSizes.js
- run:
environment:
RELEASE_CHANNEL: experimental
command: node ./scripts/tasks/danger
lint_build:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- *run_yarn
- run: yarn lint-build
- run: scripts/circleci/check_minified_errors.sh
test_build:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: stable
command: yarn test-build --maxWorkers=2
test_build_experimental:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: experimental
command: yarn test-build --maxWorkers=2
test_build_devtools:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: stable
command: yarn test-build --maxWorkers=2
test_dom_fixtures:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- run:
name: Run DOM fixture tests
environment:
RELEASE_CHANNEL: stable
command: |
cd fixtures/dom
yarn --frozen-lockfile
yarn prestart
yarn test --maxWorkers=2
test_fuzz:
docker: *docker
environment: *environment
steps:
- checkout
- *restore_yarn_cache
- *run_yarn
- run:
name: Run fuzz tests
command: |
FUZZ_TEST_SEED=$RANDOM yarn test fuzz --maxWorkers=2
FUZZ_TEST_SEED=$RANDOM yarn test-prod fuzz --maxWorkers=2
test_build_prod:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: stable
command: yarn test-build-prod --maxWorkers=2
test_build_prod_experimental:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_yarn_cache
- *run_yarn
- run:
environment:
RELEASE_CHANNEL: experimental
command: yarn test-build-prod --maxWorkers=2
workflows:
version: 2
stable:
jobs:
- setup
- lint:
requires:
- setup
- flow:
requires:
- setup
- test_source:
requires:
- setup
- test_source_prod:
requires:
- setup
- test_source_persistent:
requires:
- setup
- build:
requires:
- setup
- process_artifacts:
requires:
- build
- sizebot:
requires:
- build
- lint_build:
requires:
- build
- test_build:
requires:
- build
- test_build_prod:
requires:
- build
- test_build_devtools:
requires:
- build
- test_dom_fixtures:
requires:
- build
experimental:
jobs:
- setup
- test_source_experimental:
requires:
- setup
- build_experimental:
requires:
- setup
- process_artifacts_experimental:
requires:
- build_experimental
- sizebot_experimental:
requires:
- build_experimental
- test_build_experimental:
requires:
- build_experimental
- test_build_prod_experimental:
requires:
- build_experimental
- lint_build:
requires:
- build_experimental
fuzz_tests:
triggers:
- schedule:
# Fuzz tests run hourly
cron: "0 * * * *"
filters:
branches:
only:
- master
jobs:
- setup
- test_fuzz:
requires:
- setup

View File

@@ -12,3 +12,10 @@ scripts/bench/benchmarks/**/*.js
# React repository clone
scripts/bench/remote-repo/
packages/react-devtools-core/dist
packages/react-devtools-extensions/chrome/build
packages/react-devtools-extensions/firefox/build
packages/react-devtools-extensions/shared/build
packages/react-devtools-inline/dist
packages/react-devtools-shell/dist

View File

@@ -12,18 +12,13 @@ module.exports = {
extends: 'fbjs',
// Stop ESLint from looking for a configuration file in parent folders
'root': true,
root: true,
plugins: [
'jest',
'no-for-of-loops',
'react',
'react-internal',
],
plugins: ['jest', 'no-for-of-loops', 'react', 'react-internal'],
parser: 'espree',
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 2017,
ecmaVersion: 8,
sourceType: 'script',
ecmaFeatures: {
experimentalObjectRestSpread: true,
@@ -40,8 +35,8 @@ module.exports = {
'dot-location': [ERROR, 'property'],
'dot-notation': ERROR,
'eol-last': ERROR,
'eqeqeq': [ERROR, 'allow-null'],
'indent': OFF,
eqeqeq: [ERROR, 'allow-null'],
indent: OFF,
'jsx-quotes': [ERROR, 'prefer-double'],
'keyword-spacing': [ERROR, {after: true, before: true}],
'no-bitwise': OFF,
@@ -51,9 +46,9 @@ module.exports = {
'no-shadow': ERROR,
'no-unused-expressions': ERROR,
'no-unused-vars': [ERROR, {args: 'none'}],
'no-use-before-define': [ERROR, {functions: false, variables: false}],
'no-use-before-define': OFF,
'no-useless-concat': OFF,
'quotes': [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true }],
quotes: [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true}],
'space-before-blocks': ERROR,
'space-before-function-paren': OFF,
'valid-typeof': [ERROR, {requireStringLiterals: true}],
@@ -65,6 +60,12 @@ module.exports = {
'no-var': ERROR,
strict: ERROR,
// Enforced by Prettier
// TODO: Prettier doesn't handle long strings or long comments. Not a big
// deal. But I turned it off because loading the plugin causes some obscure
// syntax error and it didn't seem worth investigating.
'max-len': OFF,
// React & JSX
// Our transforms set this automatically
'react/jsx-boolean-value': [ERROR, 'always'],
@@ -78,7 +79,10 @@ module.exports = {
'react/react-in-jsx-scope': ERROR,
'react/self-closing-comp': ERROR,
// We don't care to do this
'react/jsx-wrap-multilines': [ERROR, {declaration: false, assignment: false}],
'react/jsx-wrap-multilines': [
ERROR,
{declaration: false, assignment: false},
],
// Prevent for...of loops because they require a Symbol polyfill.
// You can disable this rule for code that isn't shipped (e.g. build scripts and tests).
@@ -112,6 +116,7 @@ module.exports = {
files: esNextPaths,
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 8,
sourceType: 'module',
},
rules: {
@@ -124,15 +129,27 @@ module.exports = {
rules: {
// https://github.com/jest-community/eslint-plugin-jest
'jest/no-focused-tests': ERROR,
}
}
'jest/valid-expect': ERROR,
'jest/valid-expect-in-promise': ERROR,
},
},
{
files: ['packages/react-native-renderer/**/*.js'],
globals: {
nativeFabricUIManager: true,
},
},
],
globals: {
SharedArrayBuffer: true,
spyOnDev: true,
spyOnDevAndProd: true,
spyOnProd: true,
__PROFILE__: true,
__UMD__: true,
__EXPERIMENTAL__: true,
trustedTypes: true,
},
};

11
.gitignore vendored
View File

@@ -22,3 +22,14 @@ chrome-user-data
.vscode
*.swp
*.swo
packages/react-devtools-core/dist
packages/react-devtools-extensions/chrome/build
packages/react-devtools-extensions/chrome/*.crx
packages/react-devtools-extensions/chrome/*.pem
packages/react-devtools-extensions/firefox/build
packages/react-devtools-extensions/firefox/*.xpi
packages/react-devtools-extensions/firefox/*.pem
packages/react-devtools-extensions/shared/build
packages/react-devtools-inline/dist
packages/react-devtools-shell/dist

2
.nvmrc
View File

@@ -1 +1 @@
v8.4.0
v10.16.3

6
.prettierignore Normal file
View File

@@ -0,0 +1,6 @@
packages/react-devtools-core/dist
packages/react-devtools-extensions/chrome/build
packages/react-devtools-extensions/firefox/build
packages/react-devtools-extensions/shared/build
packages/react-devtools-inline/dist
packages/react-devtools-shell/dist

View File

@@ -0,0 +1 @@
{}

View File

@@ -6,6 +6,125 @@
</summary>
</details>
## 16.10.2 (October 3, 2019)
### React DOM
* Fix regression in react-native-web by restoring order of arguments in event plugin extractors ([@necolas](https://github.com/necolas) in [#16978](https://github.com/facebook/react/pull/16978))
## 16.10.1 (September 28, 2019)
### React DOM
* Fix regression in Next.js apps by allowing Suspense mismatch during hydration to silently proceed ([@sebmarkbage](https://github.com/sebmarkbage) in [#16943](https://github.com/facebook/react/pull/16943))
## 16.10.0 (September 27, 2019)
### React DOM
* Fix edge case where a hook update wasn't being memoized. ([@sebmarkbage](http://github.com/sebmarkbage) in [#16359](https://github.com/facebook/react/pull/16359))
* Fix heuristic for determining when to hydrate, so we don't incorrectly hydrate during an update. ([@sebmarkbage](http://github.com/sebmarkbage) in [#16739](https://github.com/facebook/react/pull/16739))
* Clear additional fiber fields during unmount to save memory. ([@trueadm](http://github.com/trueadm) in [#16807](https://github.com/facebook/react/pull/16807))
* Fix bug with required text fields in Firefox. ([@halvves](http://github.com/halvves) in [#16578](https://github.com/facebook/react/pull/16578))
* Prefer `Object.is` instead of inline polyfill, when available. ([@ku8ar](http://github.com/ku8ar) in [#16212](https://github.com/facebook/react/pull/16212))
* Fix bug when mixing Suspense and error handling. ([@acdlite](http://github.com/acdlite) in [#16801](https://github.com/facebook/react/pull/16801))
### Scheduler (Experimental)
* Improve queue performance by switching its internal data structure to a min binary heap. ([@acdlite](http://github.com/acdlite) in [#16245](https://github.com/facebook/react/pull/16245))
* Use `postMessage` loop with short intervals instead of attempting to align to frame boundaries with `requestAnimationFrame`. ([@acdlite](http://github.com/acdlite) in [#16214](https://github.com/facebook/react/pull/16214))
### useSubscription
* Avoid tearing issue when a mutation happens and the previous update is still in progress. ([@bvaughn](http://github.com/bvaughn) in [#16623](https://github.com/facebook/react/pull/16623))
## 16.9.0 (August 8, 2019)
### React
* Add `<React.Profiler>` API for gathering performance measurements programmatically. ([@bvaughn](https://github.com/bvaughn) in [#15172](https://github.com/facebook/react/pull/15172))
* Remove `unstable_ConcurrentMode` in favor of `unstable_createRoot`. ([@acdlite](https://github.com/acdlite) in [#15532](https://github.com/facebook/react/pull/15532))
### React DOM
* Deprecate old names for the `UNSAFE_*` lifecycle methods. ([@bvaughn](https://github.com/bvaughn) in [#15186](https://github.com/facebook/react/pull/15186) and [@threepointone](https://github.com/threepointone) in [#16103](https://github.com/facebook/react/pull/16103))
* Deprecate `javascript:` URLs as a common attack surface. ([@sebmarkbage](https://github.com/sebmarkbage) in [#15047](https://github.com/facebook/react/pull/15047))
* Deprecate uncommon "module pattern" (factory) components. ([@sebmarkbage](https://github.com/sebmarkbage) in [#15145](https://github.com/facebook/react/pull/15145))
* Add support for the `disablePictureInPicture` attribute on `<video>`. ([@eek](https://github.com/eek) in [#15334](https://github.com/facebook/react/pull/15334))
* Add support for `onLoad` event for `<embed>`. ([@cherniavskii](https://github.com/cherniavskii) in [#15614](https://github.com/facebook/react/pull/15614))
* Add support for editing `useState` state from DevTools. ([@bvaughn](https://github.com/bvaughn) in [#14906](https://github.com/facebook/react/pull/14906))
* Add support for toggling Suspense from DevTools. ([@gaearon](https://github.com/gaearon) in [#15232](https://github.com/facebook/react/pull/15232))
* Warn when `setState` is called from `useEffect`, creating a loop. ([@gaearon](https://github.com/gaearon) in [#15180](https://github.com/facebook/react/pull/15180))
* Fix a memory leak. ([@paulshen](https://github.com/paulshen) in [#16115](https://github.com/facebook/react/pull/16115))
* Fix a crash inside `findDOMNode` for components wrapped in `<Suspense>`. ([@acdlite](https://github.com/acdlite) in [#15312](https://github.com/facebook/react/pull/15312))
* Fix pending effects from being flushed too late. ([@acdlite](https://github.com/acdlite) in [#15650](https://github.com/facebook/react/pull/15650))
* Fix incorrect argument order in a warning message. ([@brickspert](https://github.com/brickspert) in [#15345](https://github.com/facebook/react/pull/15345))
* Fix hiding Suspense fallback nodes when there is an `!important` style. ([@acdlite](https://github.com/acdlite) in [#15861](https://github.com/facebook/react/pull/15861) and [#15882](https://github.com/facebook/react/pull/15882))
* Slightly improve hydration performance. ([@bmeurer](https://github.com/bmeurer) in [#15998](https://github.com/facebook/react/pull/15998))
### React DOM Server
* Fix incorrect output for camelCase custom CSS property names. ([@bedakb](https://github.com/bedakb) in [#16167](https://github.com/facebook/react/pull/16167))
### React Test Utilities and Test Renderer
* Add `act(async () => ...)` for testing asynchronous state updates. ([@threepointone](https://github.com/threepointone) in [#14853](https://github.com/facebook/react/pull/14853))
* Add support for nesting `act` from different renderers. ([@threepointone](https://github.com/threepointone) in [#16039](https://github.com/facebook/react/pull/16039) and [#16042](https://github.com/facebook/react/pull/16042))
* Warn in Strict Mode if effects are scheduled outside an `act()` call. ([@threepointone](https://github.com/threepointone) in [#15763](https://github.com/facebook/react/pull/15763) and [#16041](https://github.com/facebook/react/pull/16041))
* Warn when using `act` from the wrong renderer. ([@threepointone](https://github.com/threepointone) in [#15756](https://github.com/facebook/react/pull/15756))
### ESLint Plugin: React Hooks
* Report Hook calls at the top level as a violation. ([gaearon](https://github.com/gaearon) in [#16455](https://github.com/facebook/react/pull/16455))
## 16.8.6 (March 27, 2019)
### React DOM
* Fix an incorrect bailout in `useReducer()`. ([@acdlite](https://github.com/acdlite) in [#15124](https://github.com/facebook/react/pull/15124))
* Fix iframe warnings in Safari DevTools. ([@renanvalentin](https://github.com/renanvalentin) in [#15099](https://github.com/facebook/react/pull/15099))
* Warn if `contextType` is set to `Context.Consumer` instead of `Context`. ([@aweary](https://github.com/aweary) in [#14831](https://github.com/facebook/react/pull/14831))
* Warn if `contextType` is set to invalid values. ([@gaearon](https://github.com/gaearon) in [#15142](https://github.com/facebook/react/pull/15142))
## 16.8.5 (March 22, 2019)
### React DOM
* Don't set the first option as selected in select tag with `size` attribute. ([@kulek1](https://github.com/kulek1) in [#14242](https://github.com/facebook/react/pull/14242))
* Improve the `useEffect(async () => ...)` warning message. ([@gaearon](https://github.com/gaearon) in [#15118](https://github.com/facebook/react/pull/15118))
* Improve the error message sometimes caused by duplicate React. ([@jaredpalmer](https://github.com/jaredpalmer) in [#15139](https://github.com/facebook/react/pull/15139))
### React DOM Server
* Improve the `useLayoutEffect` warning message when server rendering. ([@gaearon](https://github.com/gaearon) in [#15158](https://github.com/facebook/react/pull/15158))
### React Shallow Renderer
* Fix `setState` in shallow renderer to work with Hooks. ([@gaearon](https://github.com/gaearon) in [#15120](https://github.com/facebook/react/pull/15120))
* Fix shallow renderer to support `React.memo`. ([@aweary](https://github.com/aweary) in [#14816](https://github.com/facebook/react/pull/14816))
* Fix shallow renderer to support Hooks inside `forwardRef`. ([@eps1lon](https://github.com/eps1lon) in [#15100](https://github.com/facebook/react/pull/15100))
## 16.8.4 (March 5, 2019)
### React DOM and other renderers
- Fix a bug where DevTools caused a runtime error when inspecting a component that used a `useContext` hook. ([@bvaughn](https://github.com/bvaughn) in [#14940](https://github.com/facebook/react/pull/14940))
## 16.8.3 (February 21, 2019)
### React DOM
* Fix a bug that caused inputs to behave incorrectly in UMD builds. ([@gaearon](https://github.com/gaearon) in [#14914](https://github.com/facebook/react/pull/14914))
* Fix a bug that caused render phase updates to be discarded. ([@gaearon](https://github.com/gaearon) in [#14852](https://github.com/facebook/react/pull/14852))
### React DOM Server
* Unwind the context stack when a stream is destroyed without completing, to prevent incorrect values during a subsequent render. ([@overlookmotel](https://github.com/overlookmotel) in [#14706](https://github.com/facebook/react/pull/14706/))
### ESLint Plugin for React Hooks
* Add a new recommended `exhaustive-deps` rule. ([@gaearon](https://github.com/gaearon) in [#14636](https://github.com/facebook/react/pull/14636))
## 16.8.2 (February 14, 2019)
### React DOM

View File

@@ -1,3 +1,76 @@
# Code of Conduct
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct/) so that you can understand what actions will and will not be tolerated.
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official
project e-mail address, posting via an official social media account, or acting
as an appointed representative at an online or offline event. Representation of
a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at <opensource-conduct@fb.com>. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@@ -1,4 +1,4 @@
# [React](https://reactjs.org/) &middot; [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/facebook/react/blob/master/LICENSE) [![npm version](https://img.shields.io/npm/v/react.svg?style=flat)](https://www.npmjs.com/package/react) [![Coverage Status](https://img.shields.io/coveralls/facebook/react/master.svg?style=flat)](https://coveralls.io/github/facebook/react?branch=master) [![CircleCI Status](https://circleci.com/gh/facebook/react.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/facebook/react) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
# [React](https://reactjs.org/) &middot; [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/facebook/react/blob/master/LICENSE) [![npm version](https://img.shields.io/npm/v/react.svg?style=flat)](https://www.npmjs.com/package/react) [![CircleCI Status](https://circleci.com/gh/facebook/react.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/facebook/react) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
React is a JavaScript library for building user interfaces.

27
babel.config.js Normal file
View File

@@ -0,0 +1,27 @@
'use strict';
module.exports = {
plugins: [
'@babel/plugin-syntax-jsx',
'@babel/plugin-transform-react-jsx',
'@babel/plugin-transform-flow-strip-types',
['@babel/plugin-proposal-class-properties', {loose: true}],
'syntax-trailing-function-commas',
[
'@babel/plugin-proposal-object-rest-spread',
{loose: true, useBuiltIns: true},
],
['@babel/plugin-transform-template-literals', {loose: true}],
'@babel/plugin-transform-literals',
'@babel/plugin-transform-arrow-functions',
'@babel/plugin-transform-block-scoped-functions',
'@babel/plugin-transform-object-super',
'@babel/plugin-transform-shorthand-properties',
'@babel/plugin-transform-computed-properties',
'@babel/plugin-transform-for-of',
['@babel/plugin-transform-spread', {loose: true, useBuiltIns: true}],
'@babel/plugin-transform-parameters',
['@babel/plugin-transform-destructuring', {loose: true, useBuiltIns: true}],
['@babel/plugin-transform-block-scoping', {throwIfClosureRequired: true}],
],
};

View File

@@ -25,22 +25,34 @@
//
// `DANGER_GITHUB_API_TOKEN=[ENV_ABOVE] yarn danger pr https://github.com/facebook/react/pull/11865
const {markdown, danger} = require('danger');
const {markdown, danger, warn} = require('danger');
const fetch = require('node-fetch');
const {generateResultsArray} = require('./scripts/rollup/stats');
const {existsSync, readFileSync} = require('fs');
const {exec} = require('child_process');
if (!existsSync('./scripts/rollup/results.json')) {
// This must match the name of the CI job that creates the build artifacts
const RELEASE_CHANNEL =
process.env.RELEASE_CHANNEL === 'experimental' ? 'experimental' : 'stable';
const artifactsJobName =
process.env.RELEASE_CHANNEL === 'experimental'
? 'process_artifacts_experimental'
: 'process_artifacts';
if (!existsSync('./build/bundle-sizes.json')) {
// This indicates the build failed previously.
// In that case, there's nothing for the Dangerfile to do.
// Exit early to avoid leaving a redundant (and potentially confusing) PR comment.
warn(
'No bundle size information found. This indicates the build ' +
'job failed.'
);
process.exit(0);
}
const currentBuildResults = JSON.parse(
readFileSync('./scripts/rollup/results.json')
readFileSync('./build/bundle-sizes.json')
);
/**
@@ -108,18 +120,75 @@ function git(args) {
// Use git locally to grab the commit which represents the place
// where the branches differ
const upstreamRepo = danger.github.pr.base.repo.full_name;
const upstreamRef = danger.github.pr.base.ref;
await git(`remote add upstream https://github.com/${upstreamRepo}.git`);
await git('fetch upstream');
const mergeBaseCommit = await git(`merge-base HEAD upstream/${upstreamRef}`);
if (upstreamRepo !== 'facebook/react') {
// Exit unless we're running in the main repo
return;
}
const commitURL = sha =>
`http://react.zpao.com/builds/master/_commits/${sha}/results.json`;
const response = await fetch(commitURL(mergeBaseCommit));
markdown(`## Size changes (${RELEASE_CHANNEL})`);
const upstreamRef = danger.github.pr.base.ref;
await git(`remote add upstream https://github.com/facebook/react.git`);
await git('fetch upstream');
const baseCommit = await git(`merge-base HEAD upstream/${upstreamRef}`);
let previousBuildResults = null;
try {
let baseCIBuildId = null;
const statusesResponse = await fetch(
`https://api.github.com/repos/facebook/react/commits/${baseCommit}/status`
);
const {statuses, state} = await statusesResponse.json();
if (state === 'failure') {
warn(`Base commit is broken: ${baseCommit}`);
return;
}
for (let i = 0; i < statuses.length; i++) {
const status = statuses[i];
if (status.context === `ci/circleci: ${artifactsJobName}`) {
if (status.state === 'success') {
baseCIBuildId = /\/facebook\/react\/([0-9]+)/.exec(
status.target_url
)[1];
break;
}
if (status.state === 'pending') {
warn(`Build job for base commit is still pending: ${baseCommit}`);
return;
}
}
}
if (baseCIBuildId === null) {
warn(`Could not find build artifacts for base commit: ${baseCommit}`);
return;
}
const baseArtifactsInfoResponse = await fetch(
`https://circleci.com/api/v1.1/project/github/facebook/react/${baseCIBuildId}/artifacts`
);
const baseArtifactsInfo = await baseArtifactsInfoResponse.json();
for (let i = 0; i < baseArtifactsInfo.length; i++) {
const info = baseArtifactsInfo[i];
if (info.path === 'home/circleci/project/build/bundle-sizes.json') {
const resultsResponse = await fetch(info.url);
previousBuildResults = await resultsResponse.json();
break;
}
}
} catch (error) {
warn(`Failed to fetch build artifacts for base commit: ${baseCommit}`);
return;
}
if (previousBuildResults === null) {
warn(`Could not find build artifacts for base commit: ${baseCommit}`);
return;
}
// Take the JSON of the build response and
// make an array comparing the results for printing
const previousBuildResults = await response.json();
const results = generateResultsArray(
currentBuildResults,
previousBuildResults
@@ -212,7 +281,7 @@ function git(args) {
<details>
<summary>Details of bundled changes.</summary>
<p>Comparing: ${mergeBaseCommit}...${danger.github.pr.head.sha}</p>
<p>Comparing: ${baseCommit}...${danger.github.pr.head.sha}</p>
${allTables.join('\n')}
@@ -220,5 +289,7 @@ function git(args) {
</details>
`;
markdown(summary);
} else {
markdown('No significant bundle size changes to report.');
}
})();

View File

@@ -448,6 +448,11 @@ const attributes = [
read: getSVGAttribute('direction'),
},
{name: 'disabled', tagName: 'input'},
{
name: 'disablePictureInPicture',
tagName: 'video',
read: getProperty('disablepictureinpicture'),
},
{
name: 'display',
tagName: 'svg',

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 14.9</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@0.14.9/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@0.14.9/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/14.9.html">http://localhost:3000/14.9.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.0</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.0/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.0/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/15.0.html">http://localhost:3000/15.0.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.1</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.1/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.1/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/15.1.html">http://localhost:3000/15.1.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.2</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.2/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/15.2.html">http://localhost:3000/15.2.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.3</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.3/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.3/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/15.3.html">http://localhost:3000/15.3.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.4</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.4/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.4/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/15.4.html">http://localhost:3000/15.4.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.5</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.5/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.5/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/15.5.html">http://localhost:3000/15.5.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.6</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.6/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.6/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/15.6.html">http://localhost:3000/15.6.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.0</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.0/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/16.0.html">http://localhost:3000/16.0.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.1</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.1/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.1/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/16.1.html">http://localhost:3000/16.1.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.2</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.2/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/16.2.html">http://localhost:3000/16.2.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.3</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.3/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.3/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/16.3.html">http://localhost:3000/16.3.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.4</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.4/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.4/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/16.4.html">http://localhost:3000/16.4.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.5</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/schedule@0.5.0/umd/schedule.development.js"></script>
<script src="https://unpkg.com/schedule@0.5.0/umd/schedule-tracing.development.js"></script>
<script src="https://unpkg.com/react@16.5/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.5/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/16.5.html">http://localhost:3000/16.5.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.6</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/scheduler@0.10.0/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@0.10.0/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@16.6/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.6/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@2.0.0-alpha.1/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/16.6.html">http://localhost:3000/16.6.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.7</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/scheduler@0.12.0/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@0.12.0/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@16.7/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@2.0.0-alpha.1/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/16.7.html">http://localhost:3000/16.7.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React canary</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/scheduler@canary/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@canary/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@canary/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@canary/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@next/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/canary.html">http://localhost:3000/canary.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React DevTools regression test</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<iframe src="canary.html"></iframe>
<iframe src="next.html"></iframe>
<iframe src="16.7.html"></iframe>
<iframe src="16.6.html"></iframe>
<iframe src="16.5.html"></iframe>
<iframe src="16.4.html"></iframe>
<iframe src="16.3.html"></iframe>
<iframe src="16.2.html"></iframe>
<iframe src="16.1.html"></iframe>
<iframe src="16.0.html"></iframe>
<iframe src="15.6.html"></iframe>
<iframe src="15.5.html"></iframe>
<iframe src="15.4.html"></iframe>
<iframe src="15.3.html"></iframe>
<iframe src="15.2.html"></iframe>
<iframe src="15.1.html"></iframe>
<iframe src="15.0.html"></iframe>
<iframe src="14.9.html"></iframe>
</body>
</html>

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React next</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/scheduler@next/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@next/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@next/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@next/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@next/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/devtools/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/next.html">http://localhost:3000/next.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env node
const finalhandler = require('finalhandler');
const http = require('http');
const serveStatic = require('serve-static');
// Serve fixtures folder
const serve = serveStatic(__dirname, {index: 'index.html'});
// Create server
const server = http.createServer(function onRequest(req, res) {
serve(req, res, finalhandler(req, res));
});
// Listen
server.listen(3000);

View File

@@ -0,0 +1,328 @@
/* eslint-disable no-fallthrough, react/react-in-jsx-scope, react/jsx-no-undef */
/* global React ReactCache ReactDOM SchedulerTracing ScheduleTracing */
const apps = [];
const pieces = React.version.split('.');
const major =
pieces[0] === '0' ? parseInt(pieces[1], 10) : parseInt(pieces[0], 10);
const minor =
pieces[0] === '0' ? parseInt(pieces[2], 10) : parseInt(pieces[1], 10);
// Convenience wrapper to organize API features in DevTools.
function Feature({children, label, version}) {
return (
<div className="Feature">
<div className="FeatureHeader">
<code className="FeatureCode">{label}</code>
<small>{version}</small>
</div>
{children}
</div>
);
}
// Simplify interaction tracing for tests below.
let trace = null;
if (typeof SchedulerTracing !== 'undefined') {
trace = SchedulerTracing.unstable_trace;
} else if (typeof ScheduleTracing !== 'undefined') {
trace = ScheduleTracing.unstable_trace;
} else {
trace = (_, __, callback) => callback();
}
// https://github.com/facebook/react/blob/master/CHANGELOG.md
switch (major) {
case 16:
switch (minor) {
case 7:
if (typeof React.useState === 'function') {
// Hooks
function Hooks() {
const [count, setCount] = React.useState(0);
const incrementCount = React.useCallback(
() => setCount(count + 1),
[count]
);
return (
<div>
count: {count}{' '}
<button onClick={incrementCount}>increment</button>
</div>
);
}
apps.push(
<Feature key="Hooks" label="Hooks" version="16.7+">
<Hooks />
</Feature>
);
}
case 6:
// memo
function LabelComponent({label}) {
return <label>{label}</label>;
}
const AnonymousMemoized = React.memo(({label}) => (
<label>{label}</label>
));
const Memoized = React.memo(LabelComponent);
const CustomMemoized = React.memo(LabelComponent);
CustomMemoized.displayName = 'MemoizedLabelFunction';
apps.push(
<Feature key="memo" label="memo" version="16.6+">
<AnonymousMemoized label="AnonymousMemoized" />
<Memoized label="Memoized" />
<CustomMemoized label="CustomMemoized" />
</Feature>
);
// Suspense
const loadResource = ([text, ms]) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(text);
}, ms);
});
};
const getResourceKey = ([text, ms]) => text;
const Resource = ReactCache.unstable_createResource(
loadResource,
getResourceKey
);
class Suspending extends React.Component {
state = {useSuspense: false};
useSuspense = () => this.setState({useSuspense: true});
render() {
if (this.state.useSuspense) {
const text = Resource.read(['loaded', 2000]);
return text;
} else {
return <button onClick={this.useSuspense}>load data</button>;
}
}
}
apps.push(
<Feature key="Suspense" label="Suspense" version="16.6+">
<React.Suspense fallback={<div>loading...</div>}>
<Suspending />
</React.Suspense>
</Feature>
);
// lazy
const LazyWithDefaultProps = React.lazy(
() =>
new Promise(resolve => {
function FooWithDefaultProps(props) {
return (
<h1>
{props.greeting}, {props.name}
</h1>
);
}
FooWithDefaultProps.defaultProps = {
name: 'World',
greeting: 'Bonjour',
};
resolve({
default: FooWithDefaultProps,
});
})
);
apps.push(
<Feature key="lazy" label="lazy" version="16.6+">
<React.Suspense fallback={<div>loading...</div>}>
<LazyWithDefaultProps greeting="Hello" />
</React.Suspense>
</Feature>
);
case 5:
case 4:
// unstable_Profiler
class ProfilerChild extends React.Component {
state = {count: 0};
incrementCount = () =>
this.setState(prevState => ({count: prevState.count + 1}));
render() {
return (
<div>
count: {this.state.count}{' '}
<button onClick={this.incrementCount}>increment</button>
</div>
);
}
}
const onRender = (...args) => {};
const Profiler = React.unstable_Profiler || React.Profiler;
apps.push(
<Feature
key="unstable_Profiler"
label="unstable_Profiler"
version="16.4+">
<Profiler id="count" onRender={onRender}>
<div>
<ProfilerChild />
</div>
</Profiler>
</Feature>
);
case 3:
// createContext()
const LocaleContext = React.createContext();
LocaleContext.displayName = 'LocaleContext';
const ThemeContext = React.createContext();
apps.push(
<Feature key="createContext" label="createContext" version="16.3+">
<ThemeContext.Provider value="blue">
<ThemeContext.Consumer>
{theme => <div>theme: {theme}</div>}
</ThemeContext.Consumer>
</ThemeContext.Provider>
<LocaleContext.Provider value="en-US">
<LocaleContext.Consumer>
{locale => <div>locale: {locale}</div>}
</LocaleContext.Consumer>
</LocaleContext.Provider>
</Feature>
);
// forwardRef()
const AnonymousFunction = React.forwardRef((props, ref) => (
<div ref={ref}>{props.children}</div>
));
const NamedFunction = React.forwardRef(function named(props, ref) {
return <div ref={ref}>{props.children}</div>;
});
const CustomName = React.forwardRef((props, ref) => (
<div ref={ref}>{props.children}</div>
));
CustomName.displayName = 'CustomNameForwardRef';
apps.push(
<Feature key="forwardRef" label="forwardRef" version="16.3+">
<AnonymousFunction>AnonymousFunction</AnonymousFunction>
<NamedFunction>NamedFunction</NamedFunction>
<CustomName>CustomName</CustomName>
</Feature>
);
// StrictMode
class StrictModeChild extends React.Component {
render() {
return 'StrictModeChild';
}
}
apps.push(
<Feature key="StrictMode" label="StrictMode" version="16.3+">
<React.StrictMode>
<StrictModeChild />
</React.StrictMode>
</Feature>
);
// unstable_AsyncMode (later renamed to unstable_ConcurrentMode, then ConcurrentMode)
const ConcurrentMode =
React.ConcurrentMode ||
React.unstable_ConcurrentMode ||
React.unstable_AsyncMode;
apps.push(
<Feature
key="AsyncMode/ConcurrentMode"
label="AsyncMode/ConcurrentMode"
version="16.3+">
<ConcurrentMode>
<div>
unstable_AsyncMode was added in 16.3, renamed to
unstable_ConcurrentMode in 16.5, and then renamed to
ConcurrentMode in 16.7
</div>
</ConcurrentMode>
</Feature>
);
case 2:
// Fragment
apps.push(
<Feature key="Fragment" label="Fragment" version="16.4+">
<React.Fragment>
<div>one</div>
<div>two</div>
</React.Fragment>
</Feature>
);
case 1:
case 0:
default:
break;
}
break;
case 15:
break;
case 14:
break;
default:
break;
}
function Even() {
return <small>(even)</small>;
}
// Simple stateful app shared by all React versions
class SimpleApp extends React.Component {
state = {count: 0};
incrementCount = () => {
const updaterFn = prevState => ({count: prevState.count + 1});
trace('Updating count', performance.now(), () => this.setState(updaterFn));
};
render() {
const {count} = this.state;
return (
<div>
{count % 2 === 0 ? (
<span>
count: {count} <Even />
</span>
) : (
<span>count: {count}</span>
)}{' '}
<button onClick={this.incrementCount}>increment</button>
</div>
);
}
}
apps.push(
<Feature key="Simple stateful app" label="Simple stateful app" version="any">
<SimpleApp />
</Feature>
);
// This component, with the version prop, helps organize DevTools at a glance.
function TopLevelWrapperForDevTools({version}) {
let header = <h1>React {version}</h1>;
if (version.includes('canary')) {
const commitSha = version.match(/.+canary-(.+)/)[1];
header = (
<h1>
React canary{' '}
<a href={`https://github.com/facebook/react/commit/${commitSha}`}>
{commitSha}
</a>
</h1>
);
} else if (version.includes('alpha')) {
header = <h1>React next</h1>;
}
return (
<div>
{header}
{apps}
</div>
);
}
TopLevelWrapperForDevTools.displayName = 'React';
ReactDOM.render(
<TopLevelWrapperForDevTools version={React.version} />,
document.getElementById('root')
);

View File

@@ -0,0 +1,37 @@
body {
font-family: sans-serif;
font-size: 12px;
}
h1 {
margin: 0;
font-size: 20px;
}
h2 {
margin: 1rem 0 0;
}
iframe {
border: 1px solid #ddd;
border-radius: 0.5rem;
}
code {
white-space: nowrap;
}
.Feature {
margin: 1rem 0;
border-bottom: 1px solid #eee;
padding-bottom: 1rem;
}
.FeatureHeader {
font-size: 16px;
margin-bottom: 0.5rem;
}
.FeatureCode {
background-color: #eee;
padding: 0.25rem;
border-radius: 0.25rem;
}

View File

@@ -0,0 +1,313 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>TODO List</title>
<!-- DevTools -->
<script src="http://localhost:8097"></script>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/immutable@4.0.0-rc.12/dist/immutable.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<style type="text/css">
.Input {
font-size: 1rem;
padding: 0.25rem;
}
.IconButton {
padding: 0.25rem;
border: none;
background: none;
cursor: pointer;
}
.List {
margin: 0.5rem 0 0;
padding: 0;
}
.ListItem {
list-style-type: none;
}
.Label {
cursor: pointer;
padding: 0.25rem;
color: #555;
}
.Label:hover {
color: #000;
}
.IconButton {
padding: 0.25rem;
border: none;
background: none;
cursor: pointer;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { Fragment, useCallback, useState } = React;
function List(props) {
const [newItemText, setNewItemText] = useState("");
const [items, setItems] = useState([
{ id: 1, isComplete: true, text: "First" },
{ id: 2, isComplete: true, text: "Second" },
{ id: 3, isComplete: false, text: "Third" }
]);
const [uid, setUID] = useState(4);
const handleClick = useCallback(() => {
if (newItemText !== "") {
setItems([
...items,
{
id: uid,
isComplete: false,
text: newItemText
}
]);
setUID(uid + 1);
setNewItemText("");
}
}, [newItemText, items, uid]);
const handleKeyPress = useCallback(
event => {
if (event.key === "Enter") {
handleClick();
}
},
[handleClick]
);
const handleChange = useCallback(
event => {
setNewItemText(event.currentTarget.value);
},
[setNewItemText]
);
const removeItem = useCallback(
itemToRemove => setItems(items.filter(item => item !== itemToRemove)),
[items]
);
const toggleItem = useCallback(
itemToToggle => {
const index = items.indexOf(itemToToggle);
setItems(
items
.slice(0, index)
.concat({
...itemToToggle,
isComplete: !itemToToggle.isComplete
})
.concat(items.slice(index + 1))
);
},
[items]
);
return (
<Fragment>
<h1>List</h1>
<input
type="text"
placeholder="New list item..."
className="Input"
value={newItemText}
onChange={handleChange}
onKeyPress={handleKeyPress}
/>
<button
className="IconButton"
disabled={newItemText === ""}
onClick={handleClick}
>
<span role="img" aria-label="Add item">
</span>
</button>
<ul className="List">
{items.map(item => (
<ListItem
key={item.id}
item={item}
removeItem={removeItem}
toggleItem={toggleItem}
/>
))}
</ul>
</Fragment>
);
}
function ListItem({ item, removeItem, toggleItem }) {
const handleDelete = useCallback(() => {
removeItem(item);
}, [item, removeItem]);
const handleToggle = useCallback(() => {
toggleItem(item);
}, [item, toggleItem]);
return (
<li className="ListItem">
<button className="IconButton" onClick={handleDelete}>
🗑
</button>
<label className="Label">
<input
className="Input"
checked={item.isComplete}
onChange={handleToggle}
type="checkbox"
/>{" "}
{item.text}
</label>
</li>
);
}
function SimpleValues() {
return (
<ChildComponent
string="abc"
emptyString=""
number={123}
undefined={undefined}
null={null}
nan={NaN}
infinity={Infinity}
true={true}
false={false}
/>
);
}
class Custom {
_number = 42;
get number() {
return this._number;
}
}
function CustomObject() {
return <ChildComponent customObject={new Custom()} />;
}
const object = {
string: "abc",
longString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKJLMNOPQRSTUVWXYZ1234567890",
emptyString: "",
number: 123,
boolean: true,
undefined: undefined,
null: null
};
function ObjectProps() {
return (
<ChildComponent
object={{
outer: {
inner: object
}
}}
array={["first", "second", "third"]}
objectInArray={[object]}
arrayInObject={{ array: ["first", "second", "third"] }}
deepObject={{
// Known limitation: we won't go deeper than several levels.
// In the future, we might offer a way to request deeper access on demand.
a: {
b: {
c: {
d: {
e: {
f: {
g: {
h: {
i: {
j: 10
}
}
}
}
}
}
}
}
}
}}
/>
);
}
const set = new Set(['abc', 123]);
const map = new Map([['name', 'Brian'], ['food', 'sushi']]);
const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]);
const mapOfMaps = new Map([['first', map], ['second', map]]);
const typedArray = Int8Array.from([100, -100, 0]);
const immutable = Immutable.fromJS({
a: [{ hello: 'there' }, 'fixed', true],
b: 123,
c: {
'1': 'xyz',
xyz: 1,
},
});
function UnserializableProps() {
return (
<ChildComponent
map={map}
set={set}
mapOfMaps={mapOfMaps}
setOfSets={setOfSets}
typedArray={typedArray}
immutable={immutable}
/>
);
}
function ChildComponent(props: any) {
return null;
}
function InspectableElements() {
return (
<Fragment>
<SimpleValues />
<ObjectProps />
<UnserializableProps />
<CustomObject />
</Fragment>
);
}
function App() {
return (
<Fragment>
<List />
<InspectableElements />
</Fragment>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
</script>
</body>
</html>

View File

@@ -8,12 +8,16 @@ coverage
# production
build
public/scheduler-unstable_mock.development.js
public/scheduler-unstable_mock.production.min.js
public/react.development.js
public/react.production.min.js
public/react-dom.development.js
public/react-dom.production.min.js
public/react-dom-server.browser.development.js
public/react-dom-server.browser.production.min.js
public/react-dom-test-utils.development.js
public/react-dom-test-utils.production.min.js
# misc
.DS_Store

View File

@@ -7,9 +7,11 @@
},
"dependencies": {
"@babel/standalone": "^7.0.0",
"art": "^0.10.3",
"classnames": "^2.2.5",
"codemirror": "^5.40.0",
"core-js": "^2.4.1",
"jest-diff": "^24.8.0",
"prop-types": "^15.6.0",
"query-string": "^4.2.3",
"react": "^15.4.1",
@@ -18,7 +20,7 @@
},
"scripts": {
"start": "react-scripts start",
"prestart": "cp ../../build/node_modules/react/umd/react.development.js ../../build/node_modules/react-dom/umd/react-dom.development.js ../../build/node_modules/react/umd/react.production.min.js ../../build/node_modules/react-dom/umd/react-dom.production.min.js ../../build/node_modules/react-dom/umd/react-dom-server.browser.development.js ../../build/node_modules/react-dom/umd/react-dom-server.browser.production.min.js public/",
"prestart": "cp ../../build/node_modules/scheduler/umd/scheduler-unstable_mock.development.js ../../build/node_modules/scheduler/umd/scheduler-unstable_mock.production.min.js ../../build/node_modules/react/umd/react.development.js ../../build/node_modules/react-dom/umd/react-dom.development.js ../../build/node_modules/react/umd/react.production.min.js ../../build/node_modules/react-dom/umd/react-dom.production.min.js ../../build/node_modules/react-dom/umd/react-dom-server.browser.development.js ../../build/node_modules/react-dom/umd/react-dom-server.browser.production.min.js ../../build/node_modules/react-dom/umd/react-dom-test-utils.development.js ../../build/node_modules/react-dom/umd/react-dom-test-utils.production.min.js public/ && cp -a ../../build/node_modules/. node_modules",
"build": "react-scripts build && cp build/index.html build/200.html",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"

View File

@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<title>sanity test for ReactTestUtils.act</title>
</head>
<body>
this page tests whether act runs properly in a browser.
<br />
your console should say "5"
<script src="scheduler-unstable_mock.development.js"></script>
<script src="react.development.js"></script>
<script type="text/javascript">
window.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler =
window.SchedulerMock;
</script>
<script src="react-dom.development.js"></script>
<script src="react-dom-test-utils.development.js"></script>
<script>
// from ReactTestUtilsAct-test.js
function App() {
let [state, setState] = React.useState(0);
async function ticker() {
await null;
setState(x => x + 1);
}
React.useEffect(() => {
ticker();
}, [Math.min(state, 4)]);
return state;
}
async function testAsyncAct() {
const el = document.createElement("div");
await ReactTestUtils.act(async () => {
ReactDOM.render(React.createElement(App), el);
});
// all 5 ticks present and accounted for
console.log(el.innerHTML);
}
testAsyncAct();
</script>
</body>
</html>

View File

@@ -13,6 +13,30 @@
var renders = 0;
var failed = false;
var needsReactDOM = getBooleanQueryParam('needsReactDOM');
var needsCreateElement = getBooleanQueryParam('needsCreateElement');
function unmountComponent(node) {
// ReactDOM was moved into a separate package in 0.14
if (needsReactDOM) {
ReactDOM.unmountComponentAtNode(node);
} else if (React.unmountComponentAtNode) {
React.unmountComponentAtNode(node);
} else {
// Unmounting for React 0.4 and lower
React.unmountAndReleaseReactRootNode(node);
}
}
function createElement(value) {
// React.createElement replaced function invocation in 0.12
if (needsCreateElement) {
return React.createElement(value);
} else {
return value();
}
}
function getQueryParam(key) {
var pattern = new RegExp(key + '=([^&]+)(&|$)');
var matches = window.location.search.match(pattern);
@@ -35,20 +59,56 @@
function prerender() {
setStatus('Generating markup');
output.innerHTML = ReactDOMServer.renderToString(
React.createElement(Fixture)
);
return Promise.resolve()
.then(function() {
const element = createElement(Fixture);
setStatus('Markup only (No React)');
// Server rendering moved to a separate package along with ReactDOM
// in 0.14.0
if (needsReactDOM) {
return ReactDOMServer.renderToString(element);
}
// React.renderComponentToString was renamed in 0.12
if (React.renderToString) {
return React.renderToString(element);
}
// React.renderComponentToString became synchronous in React 0.9.0
if (React.renderComponentToString.length === 1) {
return React.renderComponentToString(element);
}
// Finally, React 0.4 and lower emits markup in a callback
return new Promise(function(resolve) {
React.renderComponentToString(element, resolve);
});
})
.then(function(string) {
output.innerHTML = string;
setStatus('Markup only (No React)');
})
.catch(handleError);
}
function render() {
setStatus('Hydrating');
if (ReactDOM.hydrate) {
ReactDOM.hydrate(React.createElement(Fixture), output);
var element = createElement(Fixture);
// ReactDOM was split out into another package in 0.14
if (needsReactDOM) {
// Hydration changed to a separate method in React 16
if (ReactDOM.hydrate) {
ReactDOM.hydrate(element, output);
} else {
ReactDOM.render(element, output);
}
} else if (React.render) {
// React.renderComponent was renamed in 0.12
React.render(element, output);
} else {
ReactDOM.render(React.createElement(Fixture), output);
React.renderComponent(element, output);
}
setStatus(renders > 0 ? 'Re-rendered (' + renders + 'x)' : 'Hydrated');
@@ -85,17 +145,17 @@
setStatus('Failed');
output.innerHTML = 'Please name your root component "Fixture"';
} else {
prerender();
if (getBooleanQueryParam('hydrate')) {
render();
}
prerender().then(function() {
if (getBooleanQueryParam('hydrate')) {
render();
}
});
}
}
function reloadFixture(code) {
renders = 0;
ReactDOM.unmountComponentAtNode(output);
unmountComponent(output);
injectFixture(code);
}
@@ -109,12 +169,12 @@
loadScript(getQueryParam('reactPath'))
.then(function() {
return getBooleanQueryParam('needsReactDOM')
? loadScript(getQueryParam('reactDOMPath'))
: null;
})
.then(function() {
return loadScript(getQueryParam('reactDOMServerPath'));
if (needsReactDOM) {
return Promise.all([
loadScript(getQueryParam('reactDOMPath')),
loadScript(getQueryParam('reactDOMServerPath')),
]);
}
})
.then(function() {
if (failed) {

View File

@@ -0,0 +1,97 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails react-core
*/
let React;
let TestUtils;
let TestRenderer;
global.__DEV__ = process.env.NODE_ENV !== 'production';
expect.extend(require('../toWarnDev'));
describe('unmocked scheduler', () => {
beforeEach(() => {
jest.resetModules();
React = require('react');
TestUtils = require('react-dom/test-utils');
TestRenderer = require('react-test-renderer');
});
it('flushes work only outside the outermost act() corresponding to its own renderer', () => {
let log = [];
function Effecty() {
React.useEffect(() => {
log.push('called');
}, []);
return null;
}
// in legacy mode, this tests whether an act only flushes its own effects
TestRenderer.act(() => {
TestUtils.act(() => {
TestRenderer.create(<Effecty />);
});
expect(log).toEqual([]);
});
expect(log).toEqual(['called']);
log = [];
// for doublechecking, we flip it inside out, and assert on the outermost
TestUtils.act(() => {
TestRenderer.act(() => {
TestRenderer.create(<Effecty />);
});
expect(log).toEqual(['called']);
});
expect(log).toEqual(['called']);
});
});
describe('mocked scheduler', () => {
beforeEach(() => {
jest.resetModules();
jest.mock('scheduler', () =>
require.requireActual('scheduler/unstable_mock')
);
React = require('react');
TestUtils = require('react-dom/test-utils');
TestRenderer = require('react-test-renderer');
});
afterEach(() => {
jest.unmock('scheduler');
});
it('flushes work only outside the outermost act()', () => {
let log = [];
function Effecty() {
React.useEffect(() => {
log.push('called');
}, []);
return null;
}
// with a mocked scheduler, this tests whether it flushes all work only on the outermost act
TestRenderer.act(() => {
TestUtils.act(() => {
TestRenderer.create(<Effecty />);
});
expect(log).toEqual([]);
});
expect(log).toEqual(['called']);
log = [];
// for doublechecking, we flip it inside out, and assert on the outermost
TestUtils.act(() => {
TestRenderer.act(() => {
TestRenderer.create(<Effecty />);
});
expect(log).toEqual([]);
});
expect(log).toEqual(['called']);
});
});

View File

@@ -0,0 +1,197 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails react-core
*/
let React;
let ReactDOM;
let ReactART;
let ARTSVGMode;
let ARTCurrentMode;
let TestUtils;
let TestRenderer;
let ARTTest;
global.__DEV__ = process.env.NODE_ENV !== 'production';
global.__EXPERIMENTAL__ = process.env.RELEASE_CHANNEL === 'experimental';
expect.extend(require('../toWarnDev'));
function App(props) {
return 'hello world';
}
beforeEach(() => {
jest.resetModules();
React = require('react');
ReactDOM = require('react-dom');
ReactART = require('react-art');
ARTSVGMode = require('art/modes/svg');
ARTCurrentMode = require('art/modes/current');
TestUtils = require('react-dom/test-utils');
TestRenderer = require('react-test-renderer');
ARTCurrentMode.setCurrent(ARTSVGMode);
ARTTest = function ARTTestComponent(props) {
return (
<ReactART.Surface width={150} height={200}>
<ReactART.Group>
<ReactART.Shape
d="M0,0l50,0l0,50l-50,0z"
fill={new ReactART.LinearGradient(['black', 'white'])}
key="a"
width={50}
height={50}
x={50}
y={50}
opacity={0.1}
/>
<ReactART.Shape
fill="#3C5A99"
key="b"
scale={0.5}
x={50}
y={50}
title="This is an F"
cursor="pointer">
M64.564,38.583H54l0.008-5.834c0-3.035,0.293-4.666,4.657-4.666
h5.833V16.429h-9.33c-11.213,0-15.159,5.654-15.159,15.16v6.994
h-6.99v11.652h6.99v33.815H54V50.235h9.331L64.564,38.583z
</ReactART.Shape>
</ReactART.Group>
</ReactART.Surface>
);
};
});
it("doesn't warn when you use the right act + renderer: dom", () => {
TestUtils.act(() => {
TestUtils.renderIntoDocument(<App />);
});
});
it("doesn't warn when you use the right act + renderer: test", () => {
TestRenderer.act(() => {
TestRenderer.create(<App />);
});
});
it('resets correctly across renderers', () => {
function Effecty() {
React.useEffect(() => {}, []);
return null;
}
TestUtils.act(() => {
TestRenderer.act(() => {});
expect(() => {
TestRenderer.create(<Effecty />);
}).toWarnDev(["It looks like you're using the wrong act()"], {
withoutStack: true,
});
});
});
it('warns when using the wrong act version - test + dom: render', () => {
expect(() => {
TestRenderer.act(() => {
TestUtils.renderIntoDocument(<App />);
});
}).toWarnDev(["It looks like you're using the wrong act()"], {
withoutStack: true,
});
});
it('warns when using the wrong act version - test + dom: updates', () => {
let setCtr;
function Counter(props) {
const [ctr, _setCtr] = React.useState(0);
setCtr = _setCtr;
return ctr;
}
TestUtils.renderIntoDocument(<Counter />);
expect(() => {
TestRenderer.act(() => {
setCtr(1);
});
}).toWarnDev(["It looks like you're using the wrong act()"]);
});
it('warns when using the wrong act version - dom + test: .create()', () => {
expect(() => {
TestUtils.act(() => {
TestRenderer.create(<App />);
});
}).toWarnDev(["It looks like you're using the wrong act()"], {
withoutStack: true,
});
});
it('warns when using the wrong act version - dom + test: .update()', () => {
const root = TestRenderer.create(<App key="one" />);
expect(() => {
TestUtils.act(() => {
root.update(<App key="two" />);
});
}).toWarnDev(["It looks like you're using the wrong act()"], {
withoutStack: true,
});
});
it('warns when using the wrong act version - dom + test: updates', () => {
let setCtr;
function Counter(props) {
const [ctr, _setCtr] = React.useState(0);
setCtr = _setCtr;
return ctr;
}
TestRenderer.create(<Counter />);
expect(() => {
TestUtils.act(() => {
setCtr(1);
});
}).toWarnDev(["It looks like you're using the wrong act()"]);
});
it('does not warn when nesting react-act inside react-dom', () => {
TestUtils.act(() => {
TestUtils.renderIntoDocument(<ARTTest />);
});
});
it('does not warn when nesting react-act inside react-test-renderer', () => {
TestRenderer.act(() => {
TestRenderer.create(<ARTTest />);
});
});
it("doesn't warn if you use nested acts from different renderers", () => {
TestRenderer.act(() => {
TestUtils.act(() => {
TestRenderer.create(<App />);
});
});
});
if (__EXPERIMENTAL__) {
it('warns when using createRoot() + .render', () => {
const root = ReactDOM.createRoot(document.createElement('div'));
expect(() => {
TestRenderer.act(() => {
root.render(<App />);
});
}).toWarnDev(
[
'In Concurrent or Sync modes, the "scheduler" module needs to be mocked',
"It looks like you're using the wrong act()",
],
{
withoutStack: true,
}
);
});
}

View File

@@ -4,13 +4,15 @@ import '../style.css';
const React = window.React;
function App() {
return (
<div>
<Header />
<Fixtures />
</div>
);
class App extends React.Component {
render() {
return (
<div>
<Header />
<Fixtures />
</div>
);
}
}
export default App;

View File

@@ -1,5 +1,6 @@
import {parse, stringify} from 'query-string';
import getVersionTags from '../tags';
import VersionPicker from './VersionPicker';
const React = window.React;
class Header extends React.Component {
@@ -9,18 +10,12 @@ class Header extends React.Component {
const version = query.version || 'local';
const production = query.production || false;
const versions = [version];
this.state = {version, versions, production};
}
componentWillMount() {
getVersionTags().then(tags => {
let versions = tags.map(tag => tag.name.slice(1));
versions = [`local`, ...versions];
this.setState({versions});
});
}
handleVersionChange(event) {
handleVersionChange(version) {
const query = parse(window.location.search);
query.version = event.target.value;
query.version = version;
if (query.version === 'local') {
delete query.version;
}
@@ -48,7 +43,10 @@ class Header extends React.Component {
width="20"
height="20"
/>
<a href="/">DOM Test Fixtures (v{React.version})</a>
<a href="/">
DOM Test Fixtures (v
{React.version})
</a>
</span>
<div className="header-controls">
@@ -90,17 +88,14 @@ class Header extends React.Component {
<option value="/suspense">Suspense</option>
</select>
</label>
<label htmlFor="react_version">
<label htmlFor="global_version">
<span className="sr-only">Select a version to test</span>
<select
value={this.state.version}
onChange={this.handleVersionChange}>
{this.state.versions.map(version => (
<option key={version} value={version}>
{version}
</option>
))}
</select>
<VersionPicker
id="global_version"
name="global_version"
version={this.state.version}
onChange={this.handleVersionChange}
/>
</label>
</div>
</div>

View File

@@ -0,0 +1,41 @@
import getVersionTags from '../tags';
const React = window.React;
class VersionPicker extends React.Component {
constructor(props, context) {
super(props, context);
const version = props.version || 'local';
const versions = [version];
this.state = {versions};
}
componentWillMount() {
getVersionTags().then(tags => {
let versions = tags.map(tag => tag.name.slice(1));
versions = [`local`, ...versions];
this.setState({versions});
});
}
onChange = event => {
this.props.onChange(event.target.value);
};
render() {
const {version, id, name} = this.props;
const {versions} = this.state;
return (
<select id={id} name={name} value={version} onChange={this.onChange}>
{versions.map(version => (
<option key={version} value={version}>
{version}
</option>
))}
</select>
);
}
}
export default VersionPicker;

View File

@@ -1,3 +1,5 @@
import {findDOMNode} from '../../../find-dom-node';
const React = window.React;
export class CodeEditor extends React.Component {
@@ -6,6 +8,8 @@ export class CodeEditor extends React.Component {
}
componentDidMount() {
this.textarea = findDOMNode(this);
// Important: CodeMirror incorrectly lays out the editor
// if it executes before CSS has loaded
// https://github.com/graphql/graphiql/issues/33#issuecomment-318188555
@@ -44,7 +48,6 @@ export class CodeEditor extends React.Component {
render() {
return (
<textarea
ref={ref => (this.textarea = ref)}
defaultValue={this.props.code}
autoComplete="off"
hidden={true}
@@ -72,6 +75,10 @@ export class CodeError extends React.Component {
if (supportsDetails) {
const [summary, ...body] = error.message.split(/\n+/g);
if (body.length >= 0) {
return <div className={className}>{summary}</div>;
}
return (
<details className={className}>
<summary>{summary}</summary>

View File

@@ -22,6 +22,7 @@
.hydration-options label {
font-size: 13px;
margin-right: 10px;
}
.hydration-options input[type=checkbox] {
@@ -30,6 +31,11 @@
vertical-align: middle;
}
.hydration-options select {
margin-left: 10px;
max-width: 100px;
}
.hydration .CodeMirror {
font-size: 13px;
padding-top: 8px;

View File

@@ -1,4 +1,5 @@
import './hydration.css';
import VersionPicker from '../../VersionPicker';
import {SAMPLE_CODE} from './data';
import {CodeEditor, CodeError} from './Code';
import {compile} from './code-transformer';
@@ -6,12 +7,17 @@ import {reactPaths} from '../../../react-loader';
import qs from 'query-string';
const React = window.React;
// The Hydration fixture can render at a different version than the parent
// app. This allows rendering for versions of React older than the DOM
// test fixtures can support.
const initialVersion = qs.parse(window.location.search).version || 'local';
class Hydration extends React.Component {
state = {
error: null,
code: SAMPLE_CODE,
hydrate: true,
version: initialVersion,
};
ready = false;
@@ -72,9 +78,14 @@ class Hydration extends React.Component {
});
};
setVersion = version => {
this.setState({version});
};
render() {
const {code, error, hydrate} = this.state;
const src = '/renderer.html?' + qs.stringify({hydrate, ...reactPaths()});
const {code, error, hydrate, version} = this.state;
const src =
'/renderer.html?' + qs.stringify({hydrate, ...reactPaths(version)});
return (
<div className="hydration">
@@ -89,6 +100,16 @@ class Hydration extends React.Component {
/>
Auto-Hydrate
</label>
<label htmlFor="hydration_version">
Version:
<VersionPicker
id="hydration_version"
name="hyration_version"
version={version}
onChange={this.setVersion}
/>
</label>
</header>
<CodeEditor code={code} onChange={this.setCode} />

View File

@@ -1,5 +1,6 @@
import FixtureSet from '../../FixtureSet';
import MouseMovement from './mouse-movement';
import MouseEnter from './mouse-enter';
const React = window.React;
@@ -8,6 +9,7 @@ class MouseEvents extends React.Component {
return (
<FixtureSet title="Mouse Events">
<MouseMovement />
<MouseEnter />
</FixtureSet>
);
}

View File

@@ -0,0 +1,73 @@
import TestCase from '../../TestCase';
const React = window.React;
const ReactDOM = window.ReactDOM;
const MouseEnter = () => {
const containerRef = React.useRef();
React.useEffect(function() {
const hostEl = containerRef.current;
ReactDOM.render(<MouseEnterDetect />, hostEl, () => {
ReactDOM.render(<MouseEnterDetect />, hostEl.childNodes[1]);
});
}, []);
return (
<TestCase
title="Mouse Enter"
description=""
affectedBrowsers="Chrome, Safari, Firefox">
<TestCase.Steps>
<li>Mouse enter the boxes below, from different borders</li>
</TestCase.Steps>
<TestCase.ExpectedResult>
Mouse enter call count should equal to 1; <br />
Issue{' '}
<a
rel="noopener noreferrer"
target="_blank"
href="https://github.com/facebook/react/issues/16763">
#16763
</a>{' '}
should not happen.
<br />
</TestCase.ExpectedResult>
<div ref={containerRef} />
</TestCase>
);
};
const MouseEnterDetect = () => {
const [log, setLog] = React.useState({});
const firstEl = React.useRef();
const siblingEl = React.useRef();
const onMouseEnter = e => {
const timeStamp = e.timeStamp;
setLog(log => {
const callCount = 1 + (log.timeStamp === timeStamp ? log.callCount : 0);
return {
timeStamp,
callCount,
};
});
};
return (
<React.Fragment>
<div
ref={firstEl}
onMouseEnter={onMouseEnter}
style={{
border: '1px solid #d9d9d9',
padding: '20px 20px',
}}>
Mouse enter call count: {log.callCount || ''}
</div>
<div ref={siblingEl} />
</React.Fragment>
);
};
export default MouseEnter;

View File

@@ -202,6 +202,34 @@ class SelectFixture extends React.Component {
</select>
</div>
</TestCase>
<TestCase
title="A select with the size attribute should not set first option as selected"
relatedIssues="14239"
introducedIn="16.0.0">
<TestCase.ExpectedResult>
No options should be selected.
</TestCase.ExpectedResult>
<div className="test-fixture">
<select size="3">
<option>0</option>
<option>1</option>
<option>2</option>
</select>
</div>
<p className="footnote">
<b>Notes:</b> This happens if <code>size</code> is assigned after
options are selected. The select element picks the first item by
default, then it is expanded to show more options when{' '}
<code>size</code> is assigned, preserving the default selection.
</p>
<p className="footnote">
This was introduced in React 16.0.0 when options were added before
select attribute assignment.
</p>
</TestCase>
</FixtureSet>
);
}

View File

@@ -46,7 +46,7 @@ class SuspendyTreeChild extends React.Component {
render() {
return (
<React.Fragment>
<>
<Suspense fallback={<div>(display: none)</div>}>
<div>
<AsyncStep text={`${this.state.step} + ${this.id}`} ms={500} />
@@ -54,7 +54,7 @@ class SuspendyTreeChild extends React.Component {
</div>
</Suspense>
<button onClick={this.increment}>Hide</button>
</React.Fragment>
</>
);
}
}
@@ -86,22 +86,22 @@ class SuspendyTree extends React.Component {
};
render() {
return (
<React.Fragment>
<>
<div ref={this.parentContainer}>
<div ref={this.container} />
</div>
<div>
{this.container.current !== null
? ReactDOM.createPortal(
<React.Fragment>
<>
<SuspendyTreeChild>{this.props.children}</SuspendyTreeChild>
<button onClick={this.removeAndRestore}>Remove</button>
</React.Fragment>,
</>,
this.container.current
)
: null}
</div>
</React.Fragment>
</>
);
}
}
@@ -169,7 +169,7 @@ class TextInputFixtures extends React.Component {
the "Go" button.
</li>
<li>
Intead of clicking "Go", which switches focus, press Command +
Instead of clicking "Go", which switches focus, press Command +
Enter (or Control + Enter on Windows, Linux).
</li>
</TestCase.Steps>

View File

@@ -1,3 +1,4 @@
import Fixture from '../../Fixture';
import FixtureSet from '../../FixtureSet';
import TestCase from '../../TestCase';
@@ -39,6 +40,44 @@ export default class TextAreaFixtures extends React.Component {
<textarea placeholder="Hello, world" />
</div>
</TestCase>
<TestCase
title="Required Textareas"
affectedBrowsers="Firefox"
relatedIssues="16402">
<TestCase.Steps>
<li>View this test in Firefox</li>
</TestCase.Steps>
<TestCase.ExpectedResult>
You should{' '}
<b>
<i>not</i>
</b>{' '}
see a red aura on initial page load, indicating the textarea is
invalid.
<br />
This aura looks roughly like:
<textarea style={{boxShadow: '0 0 1px 1px red', marginLeft: 8}} />
</TestCase.ExpectedResult>
<Fixture>
<form className="control-box">
<fieldset>
<legend>Empty value prop string</legend>
<textarea value="" required={true} />
</fieldset>
<fieldset>
<legend>No value prop</legend>
<textarea required={true} />
</fieldset>
<fieldset>
<legend>Empty defaultValue prop string</legend>
<textarea required={true} defaultValue="" />
</fieldset>
</form>
</Fixture>
</TestCase>
</FixtureSet>
);
}

View File

@@ -0,0 +1,20 @@
/**
* Provides a standard way to access a DOM node across all versions of
* React.
*/
import {reactPaths} from './react-loader';
const React = window.React;
const ReactDOM = window.ReactDOM;
export function findDOMNode(target) {
const {needsReactDOM} = reactPaths();
if (needsReactDOM) {
return ReactDOM.findDOMNode(target);
} else {
// eslint-disable-next-line
return React.findDOMNode(target);
}
}

View File

@@ -36,19 +36,29 @@ function loadScript(src) {
});
}
export function reactPaths() {
function getVersion() {
let query = parseQuery(window.location.search);
return query.version || 'local';
}
export function reactPaths(version = getVersion()) {
let query = parseQuery(window.location.search);
let version = query.version || 'local';
let isProduction = query.production === 'true';
let environment = isProduction ? 'production.min' : 'development';
let reactPath = 'react.' + environment + '.js';
let reactDOMPath = 'react-dom.' + environment + '.js';
let reactDOMServerPath = 'react-dom-server.browser.' + environment + '.js';
let reactPath = `react.${environment}.js`;
let reactDOMPath = `react-dom.${environment}.js`;
let reactDOMServerPath = `react-dom-server.browser.${environment}.js`;
let needsCreateElement = true;
let needsReactDOM = true;
if (version !== 'local') {
const {major, minor, prerelease} = semver(version);
if (major === 0) {
needsCreateElement = minor >= 12;
needsReactDOM = minor >= 14;
}
const [preReleaseStage] = prerelease;
// The file structure was updated in 16. This wasn't the case for alphas.
// Load the old module location for anything less than 16 RC
@@ -68,26 +78,27 @@ export function reactPaths() {
reactDOMServerPath =
'https://unpkg.com/react-dom@' +
version +
'/umd/react-dom-server.browser.' +
environment +
'.js';
} else {
let suffix = isProduction ? '.min.js' : '.js';
reactPath = 'https://unpkg.com/react@' + version + '/dist/react' + suffix;
'/umd/react-dom-server.browser' +
environment;
} else if (major > 0 || minor > 11) {
reactPath = 'https://unpkg.com/react@' + version + '/dist/react.js';
reactDOMPath =
'https://unpkg.com/react-dom@' + version + '/dist/react-dom' + suffix;
'https://unpkg.com/react-dom@' + version + '/dist/react-dom.js';
reactDOMServerPath =
'https://unpkg.com/react-dom@' +
version +
'/dist/react-dom-server' +
suffix;
'https://unpkg.com/react-dom@' + version + '/dist/react-dom-server.js';
} else {
reactPath =
'https://cdnjs.cloudflare.com/ajax/libs/react/' + version + '/react.js';
}
}
const needsReactDOM = version === 'local' || parseFloat(version, 10) > 0.13;
return {reactPath, reactDOMPath, reactDOMServerPath, needsReactDOM};
return {
reactPath,
reactDOMPath,
reactDOMServerPath,
needsCreateElement,
needsReactDOM,
};
}
export default function loadReact() {

View File

@@ -0,0 +1,291 @@
// copied from scripts/jest/matchers/toWarnDev.js
'use strict';
const jestDiff = require('jest-diff');
const util = require('util');
function shouldIgnoreConsoleError(format, args) {
if (__DEV__) {
if (typeof format === 'string') {
if (format.indexOf('Error: Uncaught [') === 0) {
// This looks like an uncaught error from invokeGuardedCallback() wrapper
// in development that is reported by jsdom. Ignore because it's noisy.
return true;
}
if (format.indexOf('The above error occurred') === 0) {
// This looks like an error addendum from ReactFiberErrorLogger.
// Ignore it too.
return true;
}
}
} else {
if (
format != null &&
typeof format.message === 'string' &&
typeof format.stack === 'string' &&
args.length === 0
) {
// In production, ReactFiberErrorLogger logs error objects directly.
// They are noisy too so we'll try to ignore them.
return true;
}
}
// Looks legit
return false;
}
function normalizeCodeLocInfo(str) {
return str && str.replace(/at .+?:\d+/g, 'at **');
}
const createMatcherFor = consoleMethod =>
function matcher(callback, expectedMessages, options = {}) {
if (__DEV__) {
// Warn about incorrect usage of matcher.
if (typeof expectedMessages === 'string') {
expectedMessages = [expectedMessages];
} else if (!Array.isArray(expectedMessages)) {
throw Error(
`toWarnDev() requires a parameter of type string or an array of strings ` +
`but was given ${typeof expectedMessages}.`
);
}
if (
options != null &&
(typeof options !== 'object' || Array.isArray(options))
) {
throw new Error(
'toWarnDev() second argument, when present, should be an object. ' +
'Did you forget to wrap the messages into an array?'
);
}
if (arguments.length > 3) {
// `matcher` comes from Jest, so it's more than 2 in practice
throw new Error(
'toWarnDev() received more than two arguments. ' +
'Did you forget to wrap the messages into an array?'
);
}
const withoutStack = options.withoutStack;
const warningsWithoutComponentStack = [];
const warningsWithComponentStack = [];
const unexpectedWarnings = [];
let lastWarningWithMismatchingFormat = null;
let lastWarningWithExtraComponentStack = null;
// Catch errors thrown by the callback,
// But only rethrow them if all test expectations have been satisfied.
// Otherwise an Error in the callback can mask a failed expectation,
// and result in a test that passes when it shouldn't.
let caughtError;
const isLikelyAComponentStack = message =>
typeof message === 'string' && message.includes('\n in ');
const consoleSpy = (format, ...args) => {
// Ignore uncaught errors reported by jsdom
// and React addendums because they're too noisy.
if (
consoleMethod === 'error' &&
shouldIgnoreConsoleError(format, args)
) {
return;
}
const message = util.format(format, ...args);
const normalizedMessage = normalizeCodeLocInfo(message);
// Remember if the number of %s interpolations
// doesn't match the number of arguments.
// We'll fail the test if it happens.
let argIndex = 0;
format.replace(/%s/g, () => argIndex++);
if (argIndex !== args.length) {
lastWarningWithMismatchingFormat = {
format,
args,
expectedArgCount: argIndex,
};
}
// Protect against accidentally passing a component stack
// to warning() which already injects the component stack.
if (
args.length >= 2 &&
isLikelyAComponentStack(args[args.length - 1]) &&
isLikelyAComponentStack(args[args.length - 2])
) {
lastWarningWithExtraComponentStack = {
format,
};
}
for (let index = 0; index < expectedMessages.length; index++) {
const expectedMessage = expectedMessages[index];
if (
normalizedMessage === expectedMessage ||
normalizedMessage.includes(expectedMessage)
) {
if (isLikelyAComponentStack(normalizedMessage)) {
warningsWithComponentStack.push(normalizedMessage);
} else {
warningsWithoutComponentStack.push(normalizedMessage);
}
expectedMessages.splice(index, 1);
return;
}
}
let errorMessage;
if (expectedMessages.length === 0) {
errorMessage =
'Unexpected warning recorded: ' +
this.utils.printReceived(normalizedMessage);
} else if (expectedMessages.length === 1) {
errorMessage =
'Unexpected warning recorded: ' +
jestDiff(expectedMessages[0], normalizedMessage);
} else {
errorMessage =
'Unexpected warning recorded: ' +
jestDiff(expectedMessages, [normalizedMessage]);
}
// Record the call stack for unexpected warnings.
// We don't throw an Error here though,
// Because it might be suppressed by ReactFiberScheduler.
unexpectedWarnings.push(new Error(errorMessage));
};
// TODO Decide whether we need to support nested toWarn* expectations.
// If we don't need it, add a check here to see if this is already our spy,
// And throw an error.
const originalMethod = console[consoleMethod];
// Avoid using Jest's built-in spy since it can't be removed.
console[consoleMethod] = consoleSpy;
try {
callback();
} catch (error) {
caughtError = error;
} finally {
// Restore the unspied method so that unexpected errors fail tests.
console[consoleMethod] = originalMethod;
// Any unexpected Errors thrown by the callback should fail the test.
// This should take precedence since unexpected errors could block warnings.
if (caughtError) {
throw caughtError;
}
// Any unexpected warnings should be treated as a failure.
if (unexpectedWarnings.length > 0) {
return {
message: () => unexpectedWarnings[0].stack,
pass: false,
};
}
// Any remaining messages indicate a failed expectations.
if (expectedMessages.length > 0) {
return {
message: () =>
`Expected warning was not recorded:\n ${this.utils.printReceived(
expectedMessages[0]
)}`,
pass: false,
};
}
if (typeof withoutStack === 'number') {
// We're expecting a particular number of warnings without stacks.
if (withoutStack !== warningsWithoutComponentStack.length) {
return {
message: () =>
`Expected ${withoutStack} warnings without a component stack but received ${
warningsWithoutComponentStack.length
}:\n` +
warningsWithoutComponentStack.map(warning =>
this.utils.printReceived(warning)
),
pass: false,
};
}
} else if (withoutStack === true) {
// We're expecting that all warnings won't have the stack.
// If some warnings have it, it's an error.
if (warningsWithComponentStack.length > 0) {
return {
message: () =>
`Received warning unexpectedly includes a component stack:\n ${this.utils.printReceived(
warningsWithComponentStack[0]
)}\nIf this warning intentionally includes the component stack, remove ` +
`{withoutStack: true} from the toWarnDev() call. If you have a mix of ` +
`warnings with and without stack in one toWarnDev() call, pass ` +
`{withoutStack: N} where N is the number of warnings without stacks.`,
pass: false,
};
}
} else if (withoutStack === false || withoutStack === undefined) {
// We're expecting that all warnings *do* have the stack (default).
// If some warnings don't have it, it's an error.
if (warningsWithoutComponentStack.length > 0) {
return {
message: () =>
`Received warning unexpectedly does not include a component stack:\n ${this.utils.printReceived(
warningsWithoutComponentStack[0]
)}\nIf this warning intentionally omits the component stack, add ` +
`{withoutStack: true} to the toWarnDev() call.`,
pass: false,
};
}
} else {
throw Error(
`The second argument for toWarnDev(), when specified, must be an object. It may have a ` +
`property called "withoutStack" whose value may be undefined, boolean, or a number. ` +
`Instead received ${typeof withoutStack}.`
);
}
if (lastWarningWithMismatchingFormat !== null) {
return {
message: () =>
`Received ${
lastWarningWithMismatchingFormat.args.length
} arguments for a message with ${
lastWarningWithMismatchingFormat.expectedArgCount
} placeholders:\n ${this.utils.printReceived(
lastWarningWithMismatchingFormat.format
)}`,
pass: false,
};
}
if (lastWarningWithExtraComponentStack !== null) {
return {
message: () =>
`Received more than one component stack for a warning:\n ${this.utils.printReceived(
lastWarningWithExtraComponentStack.format
)}\nDid you accidentally pass a stack to warning() as the last argument? ` +
`Don't forget warning() already injects the component stack automatically.`,
pass: false,
};
}
return {pass: true};
}
} else {
// Any uncaught errors or warnings should fail tests in production mode.
callback();
return {pass: true};
}
};
module.exports = {
toLowPriorityWarnDev: createMatcherFor('warn'),
toWarnDev: createMatcherFor('error'),
};

View File

@@ -6,6 +6,40 @@
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.0.0.tgz#856446641620c1c5f0ca775621d478324ebd1f52"
"@jest/types@^24.8.0":
version "24.8.0"
resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad"
integrity sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg==
dependencies:
"@types/istanbul-lib-coverage" "^2.0.0"
"@types/istanbul-reports" "^1.1.1"
"@types/yargs" "^12.0.9"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==
"@types/istanbul-lib-report@*":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c"
integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==
dependencies:
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-reports@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a"
integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==
dependencies:
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*"
"@types/yargs@^12.0.9":
version "12.0.12"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916"
integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==
abab@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d"
@@ -140,6 +174,11 @@ ansi-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
ansi-regex@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@@ -150,6 +189,13 @@ ansi-styles@^3.0.0, ansi-styles@^3.1.0:
dependencies:
color-convert "^1.9.0"
ansi-styles@^3.2.0, ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
dependencies:
color-convert "^1.9.0"
anymatch@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
@@ -249,6 +295,11 @@ arrify@^1.0.0, arrify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
art@^0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/art/-/art-0.10.3.tgz#b01d84a968ccce6208df55a733838c96caeeaea2"
integrity sha512-HXwbdofRTiJT6qZX/FnchtldzJjS3vkLJxQilc3Xj+ma2MXjY4UAyQ0ls1XZYVnDvVIBiFZbC6QsvtW86TD6tQ==
asap@~2.0.3:
version "2.0.5"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
@@ -1466,6 +1517,15 @@ chalk@^2.0.0, chalk@^2.1.0:
escape-string-regexp "^1.0.5"
supports-color "^4.0.0"
chalk@^2.0.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chokidar@^1.6.0, chokidar@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
@@ -2058,6 +2118,11 @@ detect-port-alt@1.1.3:
address "^1.0.1"
debug "^2.6.0"
diff-sequences@^24.3.0:
version "24.3.0"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975"
integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==
diff@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.0.tgz#056695150d7aa93237ca7e378ac3b1682b7963b9"
@@ -3119,6 +3184,11 @@ has-flag@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -3770,6 +3840,16 @@ jest-diff@^20.0.3:
jest-matcher-utils "^20.0.3"
pretty-format "^20.0.3"
jest-diff@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172"
integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g==
dependencies:
chalk "^2.0.1"
diff-sequences "^24.3.0"
jest-get-type "^24.8.0"
pretty-format "^24.8.0"
jest-docblock@^20.0.3:
version "20.0.3"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712"
@@ -3789,6 +3869,11 @@ jest-environment-node@^20.0.3:
jest-mock "^20.0.3"
jest-util "^20.0.3"
jest-get-type@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.8.0.tgz#a7440de30b651f5a70ea3ed7ff073a32dfe646fc"
integrity sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ==
jest-haste-map@^20.0.4:
version "20.0.5"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.0.5.tgz#abad74efb1a005974a7b6517e11010709cab9112"
@@ -5243,6 +5328,16 @@ pretty-format@^20.0.3:
ansi-regex "^2.1.1"
ansi-styles "^3.0.0"
pretty-format@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2"
integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw==
dependencies:
"@jest/types" "^24.8.0"
ansi-regex "^4.0.0"
ansi-styles "^3.2.0"
react-is "^16.8.4"
private@^0.1.6:
version "0.1.6"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.6.tgz#55c6a976d0f9bafb9924851350fe47b9b5fbb7c1"
@@ -5429,6 +5524,11 @@ react-error-overlay@^1.0.10:
settle-promise "1.0.0"
source-map "0.5.6"
react-is@^16.8.4:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
react-scripts@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-1.0.11.tgz#483d49e27f417ec981ae415a4456120a2a2bc8c1"
@@ -6248,6 +6348,13 @@ supports-color@^4.0.0, supports-color@^4.2.1:
dependencies:
has-flag "^2.0.0"
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
dependencies:
has-flag "^3.0.0"
svgo@^0.7.0:
version "0.7.1"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.1.tgz#287320fed972cb097e72c2bb1685f96fe08f8034"

View File

@@ -1,7 +1,7 @@
{
"root": true,
"parserOptions": {
"ecmaVersion": 6,
"ecmaVersion": 8,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true

View File

@@ -105,9 +105,51 @@
<div><b>Actual:</b></div>
<div id="test-8"></div>
</li>
<li>
<p>Can force a specific framerate</p>
<p><b>IMPORTANT:</b> This test may be flaky if other tests have been run in this js instance. To get a clean test refresh the page before running test 9</p>
<button onClick="runTestNine()">Run Test 9</button>
<div><b>Expected:</b></div>
<div id="test-9-expected">
</div>
<div> -------------------------------------------------</div>
<div> If you see the same above and below it's correct.
<div> -------------------------------------------------</div>
<div><b>Actual:</b></div>
<div id="test-9"></div>
</div>
</li>
<li>
<p>Runs scheduled JS work for 99% of the frame time when nothing else is using the thread.</p>
<p><b>NOTE:</b> Try this test both when nothing else is running and when something is using the compositor thread in another visible tab with video or <a href="https://www.shadertoy.com/view/MtffDX">WebGL content</a> (Shift+Click).</p>
<button onClick="runTestTen()">Run Test 10</button>
<div><b>Expected:</b></div>
<div id="test-10-expected">
</div>
<div> -------------------------------------------------</div>
<div> If you see the same above and below it's correct.
<div> -------------------------------------------------</div>
<div><b>Actual:</b></div>
<div id="test-10"></div>
</div>
</li>
<li>
<p>Runs scheduled JS work more than 95% of the frame time when inserting DOM nodes.</p>
<p><b>NOTE:</b> Try this test both when nothing else is running and when something is using the compositor thread in another visible tab with video or <a href="https://www.shadertoy.com/view/MtffDX">WebGL content</a> (Shift+Click).</p>
<button onClick="runTestEleven()">Run Test 11</button>
<div><b>Expected:</b></div>
<div id="test-11-expected">
</div>
<div> -------------------------------------------------</div>
<div> If you see the same above and below it's correct.
<div> -------------------------------------------------</div>
<div><b>Actual:</b></div>
<div id="test-11"></div>
</div>
</li>
</ol>
<script src="../../build/node_modules/react/umd/react.development.js"></script>
<script src="../../build/node_modules/scheduler/umd/scheduler.development.js"></script>
<script src="../../build/node_modules/react/umd/react.production.min.js"></script>
<script src="../../build/node_modules/scheduler/umd/scheduler.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
<script type="text/babel">
const {
@@ -117,6 +159,9 @@ const {
unstable_getFirstCallbackNode: getFirstCallbackNode,
unstable_pauseExecution: pauseExecution,
unstable_continueExecution: continueExecution,
unstable_forceFrameRate: forceFrameRate,
unstable_shouldYield: shouldYield,
unstable_NormalPriority: NormalPriority,
} = Scheduler;
function displayTestResult(testNumber) {
const expectationNode = document.getElementById('test-' + testNumber + '-expected');
@@ -188,7 +233,7 @@ const expectedResults = [
[
'scheduled Cb1',
'frame 1 started',
'cb1 called with argument of {"didTimeout":false}',
'cb1 called with argument of false',
'frame 2 started',
'frame 3 started... we stop counting now.',
],
@@ -197,8 +242,8 @@ const expectedResults = [
'scheduled CbA',
'scheduled CbB',
'frame 1 started',
'cbA called with argument of {"didTimeout":false}',
'cbB called with argument of {"didTimeout":false}',
'cbA called with argument of false',
'cbB called with argument of false',
'frame 2 started',
'frame 3 started... we stop counting now.',
],
@@ -208,9 +253,9 @@ const expectedResults = [
'scheduled CbB',
'frame 1 started',
'scheduled CbA again',
'cbA0 called with argument of {"didTimeout":false}',
'cbB called with argument of {"didTimeout":false}',
'cbA1 called with argument of {"didTimeout":false}',
'cbA0 called with argument of false',
'cbB called with argument of false',
'cbA1 called with argument of false',
'frame 2 started',
'frame 3 started... we stop counting now.',
],
@@ -222,11 +267,11 @@ const expectedResults = [
'scheduled cbD',
'frame 1 started',
'cbC called with argument of {"didTimeout":true}',
'cbA called with argument of {"didTimeout":false}',
'cbA called with argument of false',
'cbA running and taking some time',
'frame 2 started',
'cbB called with argument of {"didTimeout":false}',
'cbD called with argument of {"didTimeout":false}',
'cbB called with argument of false',
'cbD called with argument of false',
'frame 3 started... we stop counting now.',
],
// test 5
@@ -243,6 +288,23 @@ const expectedResults = [
'Finishing...',
'Done!',
],
// test 9
[
'Forcing new frame times...',
'Using new frame time!',
'Using new frame time!',
'Finished!',
],
// test 10
[
'Running work for 10 seconds...',
'Ran scheduled work for >99% of the time.',
],
// test 11
[
'Running work for 10 seconds...',
'Ran scheduled work for >95% of the time.',
],
];
function runTestOne() {
// Test 1
@@ -253,7 +315,7 @@ function runTestOne() {
const cb1 = (x) => {
updateTestResult(1, 'cb1 called with argument of ' + JSON.stringify(x));
}
scheduleCallback(cb1);
scheduleCallback(NormalPriority, cb1);
updateTestResult(1, 'scheduled Cb1');
logWhenFramesStart(1, () => {
displayTestResult(1);
@@ -271,9 +333,9 @@ function runTestTwo() {
const cbB = (x) => {
updateTestResult(2, 'cbB called with argument of ' + JSON.stringify(x));
}
scheduleCallback(cbA);
scheduleCallback(NormalPriority, cbA);
updateTestResult(2, 'scheduled CbA');
scheduleCallback(cbB);
scheduleCallback(NormalPriority, cbB);
updateTestResult(2, 'scheduled CbB');
logWhenFramesStart(2, () => {
displayTestResult(2);
@@ -288,7 +350,7 @@ function runTestThree() {
let callbackAIterations = 0;
const cbA = (x) => {
if (callbackAIterations < 1) {
scheduleCallback(cbA);
scheduleCallback(NormalPriority, cbA);
updateTestResult(3, 'scheduled CbA again');
}
updateTestResult(3, 'cbA' + callbackAIterations + ' called with argument of ' + JSON.stringify(x));
@@ -297,9 +359,9 @@ function runTestThree() {
const cbB = (x) => {
updateTestResult(3, 'cbB called with argument of ' + JSON.stringify(x));
}
scheduleCallback(cbA);
scheduleCallback(NormalPriority, cbA);
updateTestResult(3, 'scheduled CbA');
scheduleCallback(cbB);
scheduleCallback(NormalPriority, cbB);
updateTestResult(3, 'scheduled CbB');
logWhenFramesStart(3, () => {
displayTestResult(3);
@@ -333,13 +395,13 @@ function runTestFour() {
const cbD = (x) => {
updateTestResult(4, 'cbD called with argument of ' + JSON.stringify(x));
}
scheduleCallback(cbA); // won't time out
scheduleCallback(NormalPriority, cbA); // won't time out
updateTestResult(4, 'scheduled cbA');
scheduleCallback(cbB, {timeout: 100}); // times out later
scheduleCallback(NormalPriority, cbB, {timeout: 100}); // times out later
updateTestResult(4, 'scheduled cbB');
scheduleCallback(cbC, {timeout: 1}); // will time out fast
scheduleCallback(NormalPriority, cbC, {timeout: 1}); // will time out fast
updateTestResult(4, 'scheduled cbC');
scheduleCallback(cbD); // won't time out
scheduleCallback(NormalPriority, cbD); // won't time out
updateTestResult(4, 'scheduled cbD');
// should have run in order of C, A, B, D
@@ -418,15 +480,15 @@ function runTestFive() {
});
});
});
scheduleCallback(cbA);
scheduleCallback(NormalPriority, cbA);
console.log('scheduled cbA');
scheduleCallback(cbB); // will throw error
scheduleCallback(NormalPriority, cbB); // will throw error
console.log('scheduled cbB');
scheduleCallback(cbC);
scheduleCallback(NormalPriority, cbC);
console.log('scheduled cbC');
scheduleCallback(cbD); // will throw error
scheduleCallback(NormalPriority, cbD); // will throw error
console.log('scheduled cbD');
scheduleCallback(cbE);
scheduleCallback(NormalPriority, cbE);
console.log('scheduled cbE');
};
}
@@ -496,15 +558,15 @@ function runTestSix() {
});
});
});
scheduleCallback(cbA);
scheduleCallback(NormalPriority, cbA);
console.log('scheduled cbA');
scheduleCallback(cbB); // will throw error
scheduleCallback(NormalPriority, cbB); // will throw error
console.log('scheduled cbB');
scheduleCallback(cbC, {timeout: 1});
scheduleCallback(NormalPriority, cbC, {timeout: 1});
console.log('scheduled cbC');
scheduleCallback(cbD, {timeout: 1}); // will throw error
scheduleCallback(NormalPriority, cbD, {timeout: 1}); // will throw error
console.log('scheduled cbD');
scheduleCallback(cbE, {timeout: 1});
scheduleCallback(NormalPriority, cbE, {timeout: 1});
console.log('scheduled cbE');
};
}
@@ -520,9 +582,9 @@ function runTestSeven() {
counter++;
counterNode.innerHTML = counter;
waitForTimeToPass(100);
scheduleCallback(incrementCounterAndScheduleNextCallback);
scheduleCallback(NormalPriority, incrementCounterAndScheduleNextCallback);
}
scheduleCallback(incrementCounterAndScheduleNextCallback);
scheduleCallback(NormalPriority, incrementCounterAndScheduleNextCallback);
}
function runTestEight() {
@@ -542,18 +604,18 @@ function runTestEight() {
return count;
}
scheduleCallback(() => {
scheduleCallback(NormalPriority, () => {
// size should be 0
updateTestResult(8, `Queue size: ${countNodesInStack(getFirstCallbackNode())}.`);
updateTestResult(8, 'Pausing... press continue to resume.');
pauseExecution();
scheduleCallback(function () {
scheduleCallback(NormalPriority, function () {
updateTestResult(8, 'Finishing...');
displayTestResult(8);
})
scheduleCallback(function () {
scheduleCallback(NormalPriority, function () {
updateTestResult(8, 'Done!');
displayTestResult(8);
checkTestResult(8);
@@ -569,6 +631,101 @@ function continueTestEight() {
continueExecution();
}
function runTestNine() {
clearTestResult(9);
// We have this to make sure that the thing that goes right after it can get a full frame
var forceFrameFinish = () => {
while (!shouldYield()) {
waitForTimeToPass(1);
}
waitForTimeToPass(100);
}
scheduleCallback(NormalPriority, forceFrameFinish);
scheduleCallback(NormalPriority, () => {
var startTime = now();
while (!shouldYield()) {}
var initialFrameTime = now() - startTime;
var newFrameTime = (initialFrameTime * 2) > 60 ? (initialFrameTime * 2) : 60;
var newFrameRate = Math.floor(1000/newFrameTime);
updateTestResult(9, `Forcing new frame times...`);
displayTestResult(9);
forceFrameRate(newFrameRate);
var toSchedule = (again) => {
var startTime = now();
while (!shouldYield()) {}
var frameTime = now() - startTime;
if (frameTime >= (newFrameTime-8)) {
updateTestResult(9, `Using new frame time!`);
} else {
updateTestResult(9, `Failed to use new frame time. (off by ${newFrameTime - frameTime}ms)`);
}
displayTestResult(9);
if (again) {
scheduleCallback(NormalPriority, forceFrameFinish);
scheduleCallback(NormalPriority, () => {toSchedule(false);});
} else {
updateTestResult(9, `Finished!`);
forceFrameRate(0);
displayTestResult(9);
checkTestResult(9);
}
}
scheduleCallback(NormalPriority, forceFrameFinish);
scheduleCallback(NormalPriority, () => {toSchedule(true);});
});
}
function runTestTen() {
clearTestResult(10);
updateTestResult(10, `Running work for 10 seconds...`);
var testStartTime = now();
var accumulatedWork = 0
function loop() {
var startTime = now();
while (!shouldYield()) {}
var endTime = now();
accumulatedWork += endTime - startTime;
var runTime = endTime - testStartTime;
if (runTime > 10000) {
updateTestResult(10, `Ran scheduled work for ${(100 * accumulatedWork / runTime).toFixed(2)}% of the time.`);
displayTestResult(10);
return;
}
scheduleCallback(NormalPriority, loop);
}
scheduleCallback(NormalPriority, loop);
}
function runTestEleven() {
clearTestResult(11);
updateTestResult(11, `Running work for 10 seconds...`);
var testStartTime = now();
var lastInsertion = 0;
var accumulatedWork = 0
function loop() {
var startTime = now();
var timeSinceLastDOMInteraction = startTime - lastInsertion;
if (timeSinceLastDOMInteraction > 15) {
lastInsertion = startTime;
var node = document.createElement('div');
node.textContent = startTime;
document.body.appendChild(node);
document.body.clientHeight; // force layout
}
while (!shouldYield()) {}
var endTime = now();
accumulatedWork += endTime - startTime;
var runTime = endTime - testStartTime;
if (runTime > 10000) {
updateTestResult(11, `Ran scheduled work for ${(100 * accumulatedWork / runTime).toFixed(2)}% of the time.`);
displayTestResult(11);
return;
}
scheduleCallback(NormalPriority, loop);
}
scheduleCallback(NormalPriority, loop);
}
</script type="text/babel">
</body>
</html>
</html>

View File

@@ -26,7 +26,16 @@ export default class Chrome extends Component {
<Theme.Provider value={this.state.theme}>
{this.props.children}
<div>
<ThemeToggleButton onChange={theme => this.setState({theme})} />
<ThemeToggleButton
onChange={theme => {
React.unstable_withSuspenseConfig(
() => {
this.setState({theme});
},
{timeoutMs: 6000}
);
}}
/>
</div>
</Theme.Provider>
<script

View File

@@ -36,7 +36,8 @@ function checkSchedulerAPI() {
throw 'API is not defined';
}
if (Scheduler.unstable_now() !== performance.now()) {
const abs = Math.abs(Scheduler.unstable_now() - performance.now());
if (typeof abs !== 'number' || Number.isNaN(abs) || abs > 5) {
throw 'API does not work';
}
@@ -175,7 +176,7 @@ function checkEndToEndIntegration() {
SchedulerTracing.unstable_trace('render', 123, () => {
ReactDOM.render(
React.createElement(
React.unstable_Profiler,
React.Profiler,
{id: 'profiler', onRender},
React.createElement('div', null, 'hi')
),

View File

@@ -1,14 +0,0 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
node_modules
# testing
coverage
# production
build
# misc
.DS_Store
npm-debug.log

View File

@@ -1,31 +0,0 @@
# IO "suspense" demo
## What is this fixture?
This is a demo application based on [Dan Abramov's](https://github.com/gaearon) recent [JSConf Iceland talk](https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html) about React.
It depends on a local build of React and enables us to easily test async and "suspense" APIs in a more "real world app" like context.
## Can I use this code in production?
No. The APIs being tested here are unstable and some of them have still not been released to NPM. For now, this fixture is only a test harness.
## How do I run this fixture?
Clone the React repository.
Follow these steps:
```shell
# 1: Build react from source
cd /path/to/react
yarn
yarn build react-dom/index,react/index,react-cache,scheduler --type=NODE
# 2: Install fixture dependencies
cd fixtures/unstable-async/suspense/
yarn
# 3: Run the app
yarn start
```

View File

@@ -1,40 +0,0 @@
{
"name": "io-demo",
"version": "0.1.0",
"private": true,
"homepage": ".",
"devDependencies": {
"gh-pages": "^1.1.0",
"react-scripts": "^1.1.4"
},
"dependencies": {
"clipboard": "^1.7.1",
"github-fork-ribbon-css": "^0.2.1",
"react-draggable": "^3.0.5"
},
"scripts": {
"prestart": "cp -r ../../../build/node_modules/* ./node_modules/",
"prebuild": "cp -r ../../../build/node_modules/* ./node_modules/",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"deploy": "gh-pages -d build"
},
"eslintConfig": {
"extends": "./node_modules/react-scripts/config/eslint.js"
},
"browserslist": {
"development": [
"last 2 chrome versions",
"last 2 firefox versions",
"last 2 edge versions"
],
"production": [
">1%",
"last 4 versions",
"Firefox ESR",
"not ie < 11"
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,13 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="./src/favicon.ico">
<title>React Core Team</title>
</head>
<body>
<div id="root"></div>
<div id="debugger"></div>
</body>
</html>

View File

@@ -1,15 +0,0 @@
{
"short_name": "Emoji Search",
"name": "Emoji Search Example App",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@@ -1,334 +0,0 @@
export const coreContributorListJSON = [
{
id: 'acdlite',
name: 'Andrew Clark',
},
{
id: 'bvaughn',
name: 'Brian Vaughn',
},
{
id: 'gaearon',
name: 'Dan Abramov',
},
{
id: 'trueadm',
name: 'Dominic Gannaway',
},
{
id: 'flarnie',
name: 'Flarnie Marchan',
},
{
id: 'sebmarkbage',
name: 'Sebastian Markbåge',
},
{
id: 'sophiebits',
name: 'Sophie Alpert',
},
];
export const userProfileJSON = {
acdlite: {
id: 'acdlite',
name: 'Andrew Clark',
image: '/img/acdlite.jpeg',
location: 'Redwood City, CA',
email: 'acdlite@me.com',
tagline: 'React core at Facebook. Hi!',
},
bvaughn: {
id: 'bvaughn',
name: 'Brian Vaughn',
image: '/img/bvaughn.jpeg',
location: 'Mountain View, CA',
email: 'brian.david.vaughn@gmail.com',
tagline:
'React JS core team at @facebook; formerly at @treasure-data and @google.',
},
gaearon: {
id: 'gaearon',
name: 'Dan Abramov',
image: '/img/gaearon.jpeg',
location: 'London, UK',
email: 'dan.abramov@me.com',
tagline:
'Working on @reactjs. Co-author of Redux and Create React App. Building tools for humans.',
},
flarnie: {
id: 'flarnie',
name: 'Flarnie Marchan',
image: '/img/flarnie.jpeg',
location: 'Oakland, CA',
email: null,
tagline:
'Software Engineer at Facebook React Core Team & Co-maintainer of Draft.js',
},
sebmarkbage: {
id: 'sebmarkbage',
name: 'Sebastian Markbåge',
image: '/img/sebmarkbage.jpeg',
location: 'San Francisco',
email: 'sebastian@calyptus.eu',
tagline: null,
},
sophiebits: {
id: 'sophiebits',
name: 'Sophie Alpert',
image: '/img/sophiebits.jpeg',
location: 'California',
email: 'hi@sophiebits.com',
tagline:
'I like fixing things. eng manager of @reactjs at Facebook. ex-@khanacademy. 💎🌸 she/her. kindness, intersectional feminism, music.',
},
trueadm: {
id: 'trueadm',
name: 'Dominic Gannaway',
image: '/img/trueadm.jpeg',
location: 'London, United Kingdom',
email: null,
tagline:
'Currently an engineer on the React core team at @facebook. Author of @infernojs and t7. Enjoys coding + being a Dad.',
},
};
export const userRepositoriesListJSON = {
acdlite: [
{
name: 'recompose',
url: 'https://github.com/acdlite/recompose',
description:
'A React utility belt for function components and higher-order components.',
},
{
name: 'react-fiber-architecture',
url: 'https://github.com/acdlite/react-fiber-architecture',
description: "A description of React's new core algorithm, React Fiber",
},
{
name: 'redux-router',
url: 'https://github.com/acdlite/redux-router',
description:
'Redux bindings for React Router keep your router state inside your Redux store',
},
{
name: 'flummox',
url: 'https://github.com/acdlite/flummox',
description: 'Minimal, isomorphic Flux.',
},
{
name: 'redux-rx',
url: 'https://github.com/acdlite/redux-rx',
description: 'RxJS utilities for Redux.',
},
{
name: 'react-remarkable',
url: 'https://github.com/acdlite/react-remarkable',
description: 'A React component for rendering Markdown with remarkable',
},
],
bvaughn: [
{
name: 'react-virtualized',
url: 'https://github.com/bvaughn/react-virtualized',
description:
'React components for efficiently rendering large lists and tabular data',
},
{
name: 'redux-search',
url: 'https://github.com/bvaughn/redux-search',
description: 'Redux bindings for client-side search',
},
{
name: 'react-window',
url: 'https://github.com/bvaughn/react-window',
description:
'React components for efficiently rendering large lists and tabular data',
},
{
name: 'react-virtualized-select',
url: 'https://github.com/bvaughn/react-virtualized-select',
description:
'HOC that uses react-virtualized and react-select to display large lists of options in a drop-down',
},
{
name: 'js-search',
url: 'https://github.com/bvaughn/js-search',
description:
'JS Search is an efficient, client-side search library for JavaScript and JSON objects',
},
{
name: 'react-highlight-words',
url: 'https://github.com/bvaughn/react-highlight-words',
description:
'React component to highlight words within a larger body of text',
},
],
gaearon: [
{
name: 'facebook/react',
url: 'https://github.com/facebook/react',
description:
'A declarative, efficient, and flexible JavaScript library for building user interfaces.',
},
{
name: 'reduxjs/redux',
url: 'https://github.com/reduxjs/redux',
description: 'Predictable state container for JavaScript apps',
},
{
name: 'facebook/create-react-app',
url: 'https://github.com/facebook/create-react-app',
description: 'Create React apps with no build configuration.',
},
{
name: 'reduxjs/redux-devtools',
url: 'https://github.com/reduxjs/redux-devtools',
description:
'DevTools for Redux with hot reloading, action replay, and customizable UI',
},
{
name: 'react-dnd/react-dnd',
url: 'https://github.com/react-dnd/react-dnd',
description: 'Drag and Drop for React',
},
{
name: 'paularmstrong/normalizr',
url: 'https://github.com/paularmstrong/normalizr',
description: 'Normalizes nested JSON according to a schema',
},
],
flarnie: [
{
name: 'diffux/diffux',
url: 'https://github.com/diffux/diffux',
description: 'Perceptual diffs of responsive screenshots made simple.',
},
{
name: 'facebook/draft-js',
url: 'https://github.com/facebook/draft-js',
description: 'A React framework for building text editors.',
},
{
name: 'facebook/react',
url: 'https://github.com/facebook/react',
description:
'A declarative, efficient, and flexible JavaScript library for building user interfaces.',
},
{
name: 'facebook/jest',
url: 'https://github.com/facebook/jest',
description: '🃏 Delightful JavaScript Testing.',
},
{
name: 'Galooshi/import-js',
url: 'https://github.com/Galooshi/import-js',
description: 'A tool to simplify importing JS modules',
},
{
name: 'webpack_rails_demo',
url: 'https://github.com/flarnie/webpack_rails_demo',
description: 'Setting up webpack with Ruby on Rails: a basic demo',
},
],
sebmarkbage: [
{
name: 'art',
url: 'https://github.com/sebmarkbage/art',
description:
"Retained mode vector drawing API designed for multiple output modes. There's also a built-in SVG parser.",
},
{
name: 'ecmascript-immutable-data-structures',
url:
'https://github.com/sebmarkbage/ecmascript-immutable-data-structures',
description: null,
},
{
name: 'ocamlrun-wasm',
url: 'https://github.com/sebmarkbage/ocamlrun-wasm',
description: 'OCamlrun WebAssembly - OCaml Bytecode Interpreter in WASM',
},
{
name: 'ecmascript-generator-expression',
url: 'https://github.com/sebmarkbage/ecmascript-generator-expression',
description:
'Proposal for do Generator Expressions in ECMAScript. Work in progress. Edit Add topics',
},
{
name: 'ecmascript-undefined-propagation',
url: 'https://github.com/sebmarkbage/ecmascript-undefined-propagation',
description:
'ECMAScript proposal to relax the rules to return `undefined` for property access on `null` or `undefined` instead of throwing.',
},
{
name: 'ecmascript-shallow-equal',
url: 'https://github.com/sebmarkbage/ecmascript-shallow-equal',
description: 'A proposal for ECMAScript for Object.shallowEqual',
},
],
sophiebits: [
{
name: 'facebook/react',
url: 'https://github.com/facebook/react',
description:
'A declarative, efficient, and flexible JavaScript library for building user interfaces.',
},
{
name: 'Khan/KaTeX',
url: 'https://github.com/Khan/KaTeX',
description: 'Fast math typesetting for the web.',
},
{
name: 'facebook/react-devtools',
url: 'https://github.com/facebook/react-devtools',
description:
'An extension that allows inspection of React component hierarchy in the Chrome and Firefox Developer Tools.',
},
{
name: 'vim-awesome/vim-awesome',
url: 'https://github.com/vim-awesome/vim-awesome',
description: 'Awesome Vim plugins from across the universe',
},
{
name: 'facebook/draft-js',
url: 'https://github.com/facebook/draft-js',
description: 'A React framework for building text editors.',
},
{
name: 'es3ify',
url: 'https://github.com/sophiebits/es3ify',
description:
'Browserify transform to convert ES5 syntax to be ES3-compatible.',
},
],
trueadm: [
{
name: 'facebook/react',
url: 'https://github.com/facebook/react',
description:
'A declarative, efficient, and flexible JavaScript library for building user interfaces.',
},
{
name: 'infernojs/inferno',
url: 'https://github.com/infernojs/inferno',
description:
'An extremely fast, React-like JavaScript library for building modern user interfaces',
},
{
name: 'facebook/prepack',
url: 'https://github.com/facebook/prepack',
description: 'A JavaScript bundle optimizer.',
},
{
name: 't7',
url: 'https://github.com/trueadm/t7',
description: 'Lightweight virtual DOM templating library',
},
{
name: 'infernojs/babel-plugin-inferno',
url: 'https://github.com/infernojs/babel-plugin-inferno',
description: null,
},
],
};

View File

@@ -1,67 +0,0 @@
import {
coreContributorListJSON,
userProfileJSON,
userRepositoriesListJSON,
} from './data';
export function fetchCoreContributorListJSON() {
return makeFakeAPICall('/react/contributors', coreContributorListJSON);
}
export function fetchUserProfileJSON(id) {
return makeFakeAPICall(`/${id}/details`, userProfileJSON[id]);
}
export function fetchUserRepositoriesListJSON(id) {
return makeFakeAPICall(`/${id}/repositories`, userRepositoriesListJSON[id]);
}
let fakeRequestTime = 1000;
let onProgress = () => true;
export function setFakeRequestTime(val) {
fakeRequestTime = val;
}
export function setProgressHandler(handler) {
onProgress = handler;
}
export function setPauseNewRequests(value) {
shouldPauseNewRequests = value;
}
let shouldPauseNewRequests = false;
let notifiers = {};
let isPausedUrl = {};
export function setPaused(url, isPaused) {
const wasPaused = isPausedUrl[url];
isPausedUrl[url] = isPaused;
if (isPaused !== wasPaused) {
notifiers[url]();
}
}
function makeFakeAPICall(url, result) {
let i = 1;
return new Promise(resolve => {
isPausedUrl[url] = shouldPauseNewRequests;
function notify() {
if (!isPausedUrl[url]) {
i++;
}
onProgress(url, i, isPausedUrl[url]);
if (isPausedUrl[url]) {
return;
}
if (i === 100) {
resolve(result);
} else {
setTimeout(notify, fakeRequestTime / 100);
}
}
notifiers[url] = notify;
notify();
});
}

View File

@@ -1,89 +0,0 @@
import React, {lazy, Suspense, PureComponent} from 'react';
import {unstable_scheduleCallback} from 'scheduler';
import {
unstable_trace as trace,
unstable_wrap as wrap,
} from 'scheduler/tracing';
import Spinner from './Spinner';
import ContributorListPage from './ContributorListPage';
const UserPage = lazy(() => import('./UserPage'));
export default class App extends PureComponent {
state = {
currentId: null,
showDetail: false,
};
componentDidUpdate(prevProps, prevState) {
if (
prevState.showDetail !== this.state.showDetail ||
(prevState.currentId !== this.state.currentId && this.state.showDetail)
) {
window.scrollTo(0, 0);
}
}
handleUserClick = id => {
trace(`View ${id}`, performance.now(), () => {
trace(`View ${id} (high-pri)`, performance.now(), () =>
this.setState({
currentId: id,
})
);
unstable_scheduleCallback(
wrap(() =>
trace(`View ${id} (low-pri)`, performance.now(), () =>
this.setState({
showDetail: true,
})
)
)
);
});
};
handleBackClick = () =>
trace('View list', performance.now(), () =>
this.setState({
currentId: null,
showDetail: false,
})
);
render() {
const {currentId, showDetail} = this.state;
return showDetail
? this.renderDetail(currentId)
: this.renderList(currentId);
}
renderDetail(id) {
return (
<div>
<button
onClick={this.handleBackClick}
style={{
display: 'block',
marginBottom: '1rem',
}}>
Return to list
</button>
<Suspense maxDuration={2000} fallback={<Spinner size="large" />}>
<UserPage id={id} />
</Suspense>
</div>
);
}
renderList(loadingId) {
return (
<Suspense maxDuration={1500} fallback={<Spinner size="large" />}>
<ContributorListPage
loadingId={loadingId}
onUserClick={this.handleUserClick}
/>
</Suspense>
);
}
}

View File

@@ -1,63 +0,0 @@
import React, {Fragment} from 'react';
import {unstable_createResource} from 'react-cache';
import Spinner from './Spinner';
import {fetchCoreContributorListJSON} from '../api';
const ContributorListResource = unstable_createResource(
fetchCoreContributorListJSON
);
const ContributorListPage = ({loadingId, onUserClick}) => (
<Fragment>
<h1>React Core Team</h1>
<ul
style={{
display: 'grid',
gridGap: '0.5rem',
gridTemplateColumns: 'repeat(auto-fill, 20rem)',
padding: 0,
margin: 0,
}}>
{ContributorListResource.read().map(user => (
<ContributorListItem
key={user.id}
onClick={() => onUserClick(user.id)}
isLoading={loadingId && user.id === loadingId}
user={user}
/>
))}
</ul>
</Fragment>
);
const ContributorListItem = ({isLoading, onClick, user}) => (
<li
onClick={onClick}
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '1rem',
backgroundColor: 'var(--color-buttonBg)',
border: '1px solid var(--color-buttonBorder)',
borderRadius: '1rem',
opacity: isLoading === false ? 0.5 : 1,
cursor: isLoading ? 'default' : 'pointer',
}}
tabIndex="0">
<div>
<strong>{user.name}</strong>
<div style={{marginTop: '0.5rem'}}>{user.id}</div>
</div>
{isLoading ? (
<Spinner size="small" />
) : (
<svg width="24" height="24" viewBox="0 0 24 24">
<path fill="none" d="M0 0h24v24H0z" />
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
</svg>
)}
</li>
);
export default ContributorListPage;

View File

@@ -1,75 +0,0 @@
.Spinner {
animation: rotate 1.3s linear infinite;
}
.SpinnerContainer-large {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(270deg); }
}
.SmallSpinnerPath {
stroke-dasharray: 100;
stroke-dashoffset: 0;
transform-origin: center;
animation:
SmallDash 1.3s ease-in-out infinite;
}
@keyframes SmallDash {
0% { stroke-dashoffset: 100; }
50% {
stroke-dashoffset: 50;
transform:rotate(135deg);
}
100% {
stroke-dashoffset: 100;
transform:rotate(450deg);
}
}
.MediumSpinnerPath {
stroke-dasharray: 150;
stroke-dashoffset: 0;
transform-origin: center;
animation:
MediumDash 1.3s ease-in-out infinite;
}
@keyframes MediumDash {
0% { stroke-dashoffset: 150; }
50% {
stroke-dashoffset: 50;
transform:rotate(135deg);
}
100% {
stroke-dashoffset: 150;
transform:rotate(450deg);
}
}
.LargeSpinnerPath {
stroke-dasharray: 200;
stroke-dashoffset: 0;
transform-origin: center;
animation:
LargeDash 1.3s ease-in-out infinite;
}
@keyframes LargeDash {
0% { stroke-dashoffset: 200; }
50% {
stroke-dashoffset: 50;
transform:rotate(135deg);
}
100% {
stroke-dashoffset: 200;
transform:rotate(450deg);
}
}

View File

@@ -1,51 +0,0 @@
import React from 'react';
import './Spinner.css';
const SPINNER_SIZES = {
small: 30,
medium: 50,
large: 70,
};
const STROKE_WIDTHS = {
small: 4,
medium: 5,
large: 6,
};
const PATH_CLASS_NAMES = {
small: 'SmallSpinnerPath',
medium: 'MediumSpinnerPath',
large: 'LargeSpinnerPath',
};
// Heavily inspired by https://codepen.io/mrrocks/pen/EiplA
export default function Spinner({size = 'small'}) {
const baseSize = SPINNER_SIZES[size];
const pathSize = baseSize / 2;
const strokeWidth = STROKE_WIDTHS[size];
const pathRadius = `${baseSize / 2 - strokeWidth}px`;
const className = PATH_CLASS_NAMES[size];
const containerClassName = `SpinnerContainer SpinnerContainer-${size}`;
return (
<div className={containerClassName}>
<svg
className={className}
width={baseSize}
height={baseSize}
viewBox={`0 0 ${baseSize} ${baseSize}`}>
<circle
className="SpinnerPath"
fill="none"
stroke="currentColor"
strokeWidth={strokeWidth}
strokeLinecap="round"
cx={pathSize}
cy={pathSize}
r={pathRadius}
/>
</svg>
</div>
);
}

View File

@@ -1,170 +0,0 @@
import React, {Suspense} from 'react';
import {unstable_createResource} from 'react-cache';
import Spinner from './Spinner';
import {fetchUserProfileJSON, fetchUserRepositoriesListJSON} from '../api';
export default function UserPage({id}) {
return (
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, 20rem)',
gridGap: '1rem',
alignItems: 'start',
}}>
<UserDetails id={id} />
<Suspense maxDuration={1000} fallback={<Spinner size="medium" />}>
<Repositories id={id} />
</Suspense>
</div>
);
}
const UserDetailsResource = unstable_createResource(fetchUserProfileJSON);
function UserDetails({id}) {
const user = UserDetailsResource.read(id);
return (
<div
style={{
display: 'grid',
gridGap: '0.5rem',
width: '20rem',
padding: '1rem',
backgroundColor: 'var(--color-buttonBg)',
border: '1px solid var(--color-buttonBorder)',
borderRadius: '1rem',
}}>
<UserPicture source={user.image} />
<div
style={{
fontSize: '1.5rem',
fontWeight: 'bold',
color: 'var(--color-pageTextDark)',
}}>
{user.name}
</div>
<div style={{fontSize: '1.25rem'}}>{user.id}</div>
{user.tagline !== null && <div>{user.tagline}</div>}
<hr
style={{
width: '100%',
height: '1px',
border: 'none',
backgroundColor: '#ddd',
}}
/>
{user.location && <Location location={user.location} />}
{user.email && <Email email={user.email} />}
</div>
);
}
const Location = ({location}) => (
<div
style={{
display: 'flex',
alignItems: 'center',
}}>
<svg
viewBox="0 0 24 24"
style={{
width: '24px',
height: '24px',
marginRight: '0.5rem',
fill: 'currentColor',
}}>
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" />
<path d="M0 0h24v24H0z" fill="none" />
</svg>
{location}
</div>
);
const Email = ({email}) => (
<div
style={{
display: 'flex',
alignItems: 'center',
}}>
<svg
viewBox="0 0 24 24"
style={{
width: '24px',
height: '24px',
marginRight: '0.5rem',
fill: 'currentColor',
}}>
<path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z" />
<path d="M0 0h24v24H0z" fill="none" />
</svg>
<a href={`mailto:${email}`}>{email}</a>
</div>
);
const ImageResource = unstable_createResource(
src =>
new Promise(resolve => {
const img = new Image();
img.onload = () => resolve(src);
img.src = src;
})
);
function Img({src, alt, ...rest}) {
return <img src={ImageResource.read(src)} alt={alt} {...rest} />;
}
function UserPicture({source}) {
return (
<Suspense maxDuration={1500} fallback={<img src={source} alt="poster" />}>
<Img
src={source}
alt="profile picture"
style={{
width: '100%',
height: 'auto',
borderRadius: '0.5rem',
}}
/>
</Suspense>
);
}
const UserRepositoriesResource = unstable_createResource(
fetchUserRepositoriesListJSON
);
function Repositories({id}) {
const repos = UserRepositoriesResource.read(id);
return (
<ul
style={{
display: 'grid',
gridGap: '1rem',
padding: 0,
margin: 0,
}}>
{repos.map(repo => <Repository key={repo.name} {...repo} />)}
</ul>
);
}
function Repository({description, name, url}) {
return (
<li
style={{
display: 'grid',
gridGap: '0.5rem',
padding: '1rem',
backgroundColor: 'var(--color-buttonBg)',
border: '1px solid var(--color-buttonBorder)',
borderRadius: '1rem',
}}>
<strong>
<a href={url}>{name}</a>
</strong>
<div>{description}</div>
</li>
);
}

View File

@@ -1,90 +0,0 @@
* { box-sizing: border-box; }
:root {
--color-debuggerBg: #f7f7f7;
--color-debuggerText: #333;
--color-debuggerBorder: #e7e7e7;
--color-panelBg: #f7f7f7;
--color-panelText: #333;
--color-pageTextDark: #000;
--color-pageText: #333;
--color-pageBg: #fff;
--color-buttonBg: #f7f7f7;
--color-buttonBorder: #e7e7e7;
--pt: 8px;
}
body {
margin: 0;
padding: calc(var(--pt)*4);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
color: var(--color-pageText);
background-color: var(--color-pageBg);
}
/* -------------------------------- */
/* Debugger */
/* -------------------------------- */
#debugger {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
/* width: 100vw; */
/* height: 100vh; */
pointer-events: none;
}
.🎛 {
position: fixed;
max-width: calc(var(--pt)*28);
border-radius: var(--pt);
padding: calc(var(--pt)*2);
background-color: var(--color-debuggerBg);
border: 1px solid var(--color-debuggerBorder);
border-radius: 0.5rem;
color: var(--color-debuggerText);
pointer-events: all;
}
.🕹 {
background-color: var(--color-buttonBg);
border: 1px solid var(--color-buttonBorder);
border-radius: var(--pt);
padding: 0;
width: calc(var(--pt)*5);
height: calc(var(--pt)*5);
font-size: calc(var(--pt)*3);
line-height: 1;
font-weight: bold;
cursor: pointer;
user-select: none;
}
.🕹.👶 {
width: calc(var(--pt)*3);
height: calc(var(--pt)*3);
font-size: calc(var(--pt)*2);
}
.🕹.🐘 {
width: auto;
height: calc(var(--pt)*7);
padding: var(--pt) calc(var(--pt)*2);
}
.🕹:hover {
background-color: white;
top: -4px;
left: -4px;
box-shadow: 4px 4px 0 var(--color-buttonBorder);
}
.🕹:active {
box-shadow: none;
top: 0;
left: 0;
}

View File

@@ -1,275 +0,0 @@
import React, {Fragment, PureComponent} from 'react';
import {unstable_createRoot, render} from 'react-dom';
import {unstable_trace as trace} from 'scheduler/tracing';
import {
setFakeRequestTime,
setPaused,
setPauseNewRequests,
setProgressHandler,
} from './api';
import App from './components/App';
import Draggable from 'react-draggable';
import './index.css';
let handleReset;
class Shell extends PureComponent {
state = {
iteration: 0,
};
componentDidMount() {
handleReset = this.handleReset;
}
handleReset = () =>
this.setState(prevState => ({
iteration: prevState.iteration + 1,
}));
render() {
return <App key={this.state.iteration} />;
}
}
class Debugger extends PureComponent {
state = {
iteration: 0,
strategy: 'async',
requestTime: 1,
showDebugger: false,
pauseNewRequests: false,
waitTime: 0,
requests: {},
};
componentDidMount() {
setFakeRequestTime(this.state.requestTime * 1000);
setProgressHandler(this.handleProgress);
window.addEventListener('keydown', e => {
if (e.key.toLowerCase() === '/') {
this.setState(state => ({
showDebugger: !state.showDebugger,
}));
} else if (e.key.toLowerCase() === 'p') {
this.togglePauseRequests();
}
});
}
componentDidUpdate(prevProps, prevState) {
if (prevState.requestTime !== this.state.requestTime) {
setFakeRequestTime(this.state.requestTime * 1000);
}
}
handleReset = () => {
trace('Clear cache', performance.now(), () => {
// TODO: this is not implemented.
// cache.invalidate();
this.setState(state => ({
requests: {},
}));
handleReset();
});
};
handleProgress = (url, progress, isPaused) => {
this.setState(state => ({
requests: {
...state.requests,
[url]: {
url,
progress,
isPaused,
},
},
}));
};
togglePauseRequests = () => {
this.setState(
prevState => {
return {pauseNewRequests: !prevState.pauseNewRequests};
},
() => {
setPauseNewRequests(this.state.pauseNewRequests);
}
);
};
render() {
if (!this.state.showDebugger) {
return null;
}
return (
<Draggable cancel="input">
<div
className="🎛"
style={{
bottom: 20,
right: 20,
}}>
<div>
Latency: {this.state.requestTime} second{this.state.requestTime !==
1
? 's'
: ''}{' '}
<input
type="range"
min="0"
max="3"
step="0.5"
style={{width: '100%'}}
value={this.state.requestTime}
onChange={e => {
e.stopPropagation();
this.setState({requestTime: parseFloat(e.target.value)});
}}
/>
</div>
<label>
<input
type="checkbox"
checked={this.state.pauseNewRequests}
onChange={this.togglePauseRequests}
/>
Pause new requests
</label>
<br />
<br />
{Object.values(this.state.requests).filter(x => x.progress !== 100)
.length > 0 ? (
<Fragment>
<div style={{marginBottom: 10}}>
<b>Loading</b>
</div>
</Fragment>
) : (
<Fragment>
<div style={{marginBottom: 10}}>
<b>Loading</b>
</div>
<small style={{height: 20, display: 'block'}}>(None)</small>
</Fragment>
)}
{Object.keys(this.state.requests)
.reverse()
.map(url => {
const {progress, isPaused} = this.state.requests[url];
if (progress === 100) {
return null;
}
return (
<div
key={url}
style={{
height: 20,
width: '100%',
position: 'relative',
cursor: 'pointer',
title: isPaused ? 'Resume' : 'Pause',
}}
onClick={e => {
setPaused(url, !isPaused);
}}>
<div
style={{
height: '100%',
width: progress + '%',
position: 'absolute',
left: 0,
top: 0,
backgroundColor: isPaused ? '#fbfb0e' : '#61dafb',
zIndex: -1,
opacity: 0.8,
}}
/>
<div
style={{
fontFamily: 'monospace',
fontWeight: 'bold',
color: 'black',
}}>
{url}
</div>
</div>
);
})}
{Object.values(this.state.requests).filter(x => x.progress === 100)
.length > 0 ? (
<Fragment>
<br />
<div style={{marginBottom: 10}}>
<b>Cached</b>{' '}
<button
style={{
height: 16,
outline: 'none',
border: 'none',
background: 'none',
cursor: 'pointer',
}}
onClick={this.handleReset}>
🗑
</button>
</div>
</Fragment>
) : (
<Fragment>
<br />
<div style={{marginBottom: 10}}>
<b>Cached</b>
</div>
<small style={{height: 20, display: 'block'}}>(None)</small>
</Fragment>
)}
{Object.keys(this.state.requests)
.reverse()
.map(url => {
const {progress} = this.state.requests[url];
if (progress !== 100) {
return null;
}
return (
<div
key={url}
style={{
height: 20,
width: '100%',
position: 'relative',
}}>
<div
style={{
height: '100%',
width: progress + '%',
position: 'absolute',
left: 0,
top: 0,
backgroundColor:
progress !== 100 ? '#61dafb' : 'lightgreen',
zIndex: -1,
opacity: 0.8,
}}
/>
<div
style={{
fontFamily: 'monospace',
fontWeight: 'bold',
color: 'black',
}}>
{url}
</div>
</div>
);
})}
</div>
</Draggable>
);
}
}
unstable_createRoot(document.getElementById('root')).render(<Shell />);
render(<Debugger />, document.getElementById('debugger'));

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
import React, {PureComponent} from 'react';
import {flushSync, render} from 'react-dom';
import {unstable_scheduleCallback} from 'scheduler';
import {flushSync, unstable_createRoot} from 'react-dom';
import Scheduler from 'scheduler';
import _ from 'lodash';
import Charts from './Charts';
import Clock from './Clock';
@@ -67,7 +67,7 @@ class App extends PureComponent {
}
this._ignoreClick = true;
unstable_scheduleCallback(() => {
Scheduler.unstable_next(() => {
this.setState({showDemo: true}, () => {
this._ignoreClick = false;
});
@@ -146,9 +146,5 @@ class App extends PureComponent {
}
const container = document.getElementById('root');
render(
<React.unstable_ConcurrentMode>
<App />
</React.unstable_ConcurrentMode>,
container
);
const root = ReactDOM.unstable_createRoot(container);
root.render(<App />, container);

View File

@@ -1,14 +0,0 @@
<html>
<body>
<script src="../../build/node_modules/react/umd/react.development.js"></script>
<script src="../../build/node_modules/react-dom/umd/react-dom-unstable-fire.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
<div id="container"></div>
<script type="text/babel">
ReactFire.render(
<h1>Hello World!</h1>,
document.getElementById('container')
);
</script>
</body>
</html>

View File

@@ -1,40 +1,41 @@
{
"private": true,
"version": "16.6.1",
"workspaces": [
"packages/*"
],
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/code-frame": "^7.0.0",
"@babel/core": "^7.0.0",
"@babel/helper-module-imports": "^7.0.0",
"@babel/plugin-external-helpers": "^7.0.0",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/plugin-syntax-jsx": "^7.2.0",
"@babel/plugin-transform-arrow-functions": "^7.0.0",
"@babel/plugin-transform-async-to-generator": "^7.0.0",
"@babel/plugin-transform-block-scoped-functions": "^7.0.0",
"@babel/plugin-transform-block-scoping": "^7.0.0",
"@babel/plugin-transform-classes": "^7.0.0",
"@babel/plugin-transform-computed-properties": "^7.0.0",
"@babel/plugin-transform-destructuring": "^7.0.0",
"@babel/plugin-transform-for-of": "^7.0.0",
"@babel/plugin-transform-literals": "^7.0.0",
"@babel/plugin-transform-modules-commonjs": "^7.0.0",
"@babel/plugin-transform-object-super": "^7.0.0",
"@babel/plugin-transform-parameters": "^7.0.0",
"@babel/plugin-transform-react-jsx-source": "^7.0.0",
"@babel/plugin-transform-shorthand-properties": "^7.0.0",
"@babel/plugin-transform-spread": "^7.0.0",
"@babel/plugin-transform-template-literals": "^7.0.0",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"@babel/traverse": "^7.0.0",
"@mattiasbuelens/web-streams-polyfill": "0.1.0",
"art": "^0.10.1",
"babel-cli": "^6.6.5",
"babel-code-frame": "^6.26.0",
"babel-core": "^6.0.0",
"babel-eslint": "^10.0.0",
"babel-jest": "^23.0.1",
"babel-plugin-check-es2015-constants": "^6.5.0",
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-syntax-trailing-function-commas": "^6.5.0",
"babel-plugin-transform-async-to-generator": "^6.22.0",
"babel-plugin-transform-class-properties": "^6.11.5",
"babel-plugin-transform-es2015-arrow-functions": "^6.5.2",
"babel-plugin-transform-es2015-block-scoped-functions": "^6.5.0",
"babel-plugin-transform-es2015-block-scoping": "^6.23.0",
"babel-plugin-transform-es2015-classes": "^6.5.2",
"babel-plugin-transform-es2015-computed-properties": "^6.5.2",
"babel-plugin-transform-es2015-destructuring": "^6.5.0",
"babel-plugin-transform-es2015-for-of": "^6.5.2",
"babel-plugin-transform-es2015-literals": "^6.5.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.5.2",
"babel-plugin-transform-es2015-object-super": "^6.5.0",
"babel-plugin-transform-es2015-parameters": "^6.5.0",
"babel-plugin-transform-es2015-shorthand-properties": "^6.5.0",
"babel-plugin-transform-es2015-spread": "^6.5.2",
"babel-plugin-transform-es2015-template-literals": "^6.5.2",
"babel-plugin-transform-object-rest-spread": "^6.6.5",
"babel-plugin-transform-react-jsx-source": "^6.8.0",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-preset-react": "^6.5.0",
"babel-traverse": "^6.9.0",
"babylon": "6.18.0",
"chalk": "^1.1.3",
"cli-table": "^0.3.1",
@@ -43,38 +44,40 @@
"coveralls": "^2.11.6",
"create-react-class": "^15.6.3",
"cross-env": "^5.1.1",
"danger": "^3.0.4",
"danger": "^9.1.8",
"error-stack-parser": "^2.0.2",
"eslint": "^4.1.0",
"eslint": "^6.1.0",
"eslint-config-fbjs": "^1.1.1",
"eslint-plugin-babel": "^3.3.0",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-flowtype": "^2.25.0",
"eslint-plugin-jest": "^21.6.1",
"eslint-plugin-jest": "^22.15.0",
"eslint-plugin-no-for-of-loops": "^1.0.0",
"eslint-plugin-react": "^6.7.1",
"eslint-plugin-react-internal": "link:./scripts/eslint-rules/",
"eslint-plugin-react-internal": "link:./scripts/eslint-rules",
"fbjs-scripts": "^0.8.3",
"filesize": "^3.5.6",
"flow-bin": "^0.72.0",
"glob": "^6.0.4",
"glob-stream": "^6.1.0",
"google-closure-compiler": "20190106.0.0",
"google-closure-compiler": "20190301.0.0",
"gzip-size": "^3.0.0",
"jasmine-check": "^1.0.0-rc.0",
"jest": "^23.1.0",
"jest-diff": "^23.0.1",
"jest": "^24.9.0",
"jest-diff": "^24.9.0",
"jest-snapshot-serializer-raw": "^1.1.0",
"minimatch": "^3.0.4",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"ncp": "^2.0.0",
"object-assign": "^4.1.1",
"pacote": "^9.5.6",
"prettier": "1.13.7",
"prop-types": "^15.6.2",
"random-seed": "^0.3.0",
"react-lifecycles-compat": "^3.0.2",
"rimraf": "^2.6.1",
"rollup": "^0.52.1",
"rollup-plugin-babel": "^3.0.1",
"rollup-plugin-babel": "^4.0.1",
"rollup-plugin-commonjs": "^8.2.6",
"rollup-plugin-node-resolve": "^2.1.1",
"rollup-plugin-prettier": "^0.3.0",
@@ -84,11 +87,10 @@
"targz": "^1.0.1",
"through2": "^2.0.0",
"tmp": "~0.0.28",
"typescript": "~1.8.10",
"@mattiasbuelens/web-streams-polyfill": "0.1.0"
"typescript": "~1.8.10"
},
"devEngines": {
"node": "8.x || 9.x || 10.x || 11.x"
"node": "8.x || 9.x || 10.x || 11.x || 12.x"
},
"jest": {
"testRegex": "/scripts/jest/dont-run-jest-directly\\.js$"
@@ -98,15 +100,19 @@
"linc": "node ./scripts/tasks/linc.js",
"lint": "node ./scripts/tasks/eslint.js",
"lint-build": "node ./scripts/rollup/validate/index.js",
"postinstall": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json && node ./scripts/flow/createFlowConfigs.js",
"extract-errors": "yarn build --type=dev --extract-errors",
"postinstall": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json && node ./scripts/flow/createFlowConfigs.js && node ./scripts/yarn/downloadReactIsForPrettyFormat.js",
"debug-test": "cross-env NODE_ENV=development node --inspect-brk node_modules/.bin/jest --config ./scripts/jest/config.source.js --runInBand",
"test": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source.js",
"test-fire": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source-fire.js",
"test-persistent": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source-persistent.js",
"debug-test-persistent": "cross-env NODE_ENV=development node --inspect-brk node_modules/.bin/jest --config ./scripts/jest/config.source-persistent.js --runInBand",
"test-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.source.js",
"test-fire-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.source-fire.js",
"test-prod-build": "yarn test-build-prod",
"test-build": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.build.js",
"test-build-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.build.js",
"test-build-devtools": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.build-devtools.js",
"debug-test-build-devtools": "cross-env NODE_ENV=development node --inspect-brk node_modules/.bin/jest --config ./scripts/jest/config.build-devtools.js",
"test-dom-fixture": "cd fixtures/dom && yarn && yarn prestart && yarn test",
"flow": "node ./scripts/tasks/flow.js",
"flow-ci": "node ./scripts/tasks/flow-ci.js",
"prettier": "node ./scripts/prettier/index.js write-changed",

View File

@@ -0,0 +1,5 @@
This package is intended to eventually replace the current `@babel/plugin-transform-react-jsx`, changing the JSX transform from targeting `React.createElement(type, props, children)` to `React.jsx(types, props, key)`.
https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md
**This is experimental and not intended to be used directly.**

View File

@@ -0,0 +1,392 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable quotes */
'use strict';
const babel = require('@babel/core');
const codeFrame = require('@babel/code-frame');
const {wrap} = require('jest-snapshot-serializer-raw');
function transform(input, options) {
return wrap(
babel.transform(input, {
configFile: false,
plugins: [
'@babel/plugin-syntax-jsx',
'@babel/plugin-transform-arrow-functions',
...(options && options.development
? [
'@babel/plugin-transform-react-jsx-source',
'@babel/plugin-transform-react-jsx-self',
]
: []),
[
'./packages/babel-plugin-react-jsx',
{
development: __DEV__,
useBuiltIns: true,
useCreateElement: true,
...options,
},
],
],
}).code
);
}
describe('transform react to jsx', () => {
it('fragment with no children', () => {
expect(transform(`var x = <></>`)).toMatchSnapshot();
});
it('React.Fragment to set keys and source', () => {
expect(
transform(`var x = <React.Fragment key='foo'><div /></React.Fragment>`, {
development: true,
})
).toMatchSnapshot();
});
it('normal fragments not to set key and source', () => {
expect(
transform(`var x = <><div /></>`, {
development: true,
})
).toMatchSnapshot();
});
it('should properly handle comments adjacent to children', () => {
expect(
transform(`
var x = (
<div>
{/* A comment at the beginning */}
{/* A second comment at the beginning */}
<span>
{/* A nested comment */}
</span>
{/* A sandwiched comment */}
<br />
{/* A comment at the end */}
{/* A second comment at the end */}
</div>
);
`)
).toMatchSnapshot();
});
it('adds appropriate new lines when using spread attribute', () => {
expect(transform(`<Component {...props} sound="moo" />`)).toMatchSnapshot();
});
it('arrow functions', () => {
expect(
transform(`
var foo = function () {
return () => <this />;
};
var bar = function () {
return () => <this.foo />;
};
`)
).toMatchSnapshot();
});
it('assignment', () => {
expect(
transform(`var div = <Component {...props} foo="bar" />`)
).toMatchSnapshot();
});
it('concatenates adjacent string literals', () => {
expect(
transform(`
var x =
<div>
foo
{"bar"}
baz
<div>
buz
bang
</div>
qux
{null}
quack
</div>
`)
).toMatchSnapshot();
});
it('should allow constructor as prop', () => {
expect(transform(`<Component constructor="foo" />;`)).toMatchSnapshot();
});
it('should allow deeper js namespacing', () => {
expect(
transform(`<Namespace.DeepNamespace.Component />;`)
).toMatchSnapshot();
});
it('should allow elements as attributes', () => {
expect(transform(`<div attr=<div /> />`)).toMatchSnapshot();
});
it('should allow js namespacing', () => {
expect(transform(`<Namespace.Component />;`)).toMatchSnapshot();
});
it('should allow nested fragments', () => {
expect(
transform(`
<div>
< >
<>
<span>Hello</span>
<span>world</span>
</>
<>
<span>Goodbye</span>
<span>world</span>
</>
</>
</div>
`)
).toMatchSnapshot();
});
it('should avoid wrapping in extra parens if not needed', () => {
expect(
transform(`
var x = <div>
<Component />
</div>;
var x = <div>
{props.children}
</div>;
var x = <Composite>
{props.children}
</Composite>;
var x = <Composite>
<Composite2 />
</Composite>;
`)
).toMatchSnapshot();
});
it('should convert simple tags', () => {
expect(transform(`var x = <div></div>;`)).toMatchSnapshot();
});
it('should convert simple text', () => {
expect(transform(`var x = <div>text</div>;`)).toMatchSnapshot();
});
it('should disallow spread children', () => {
let _error;
const code = `<div>{...children}</div>;`;
try {
transform(code);
} catch (error) {
_error = error;
}
expect(_error).toEqual(
new SyntaxError(
'undefined: Spread children are not supported in React.' +
'\n' +
codeFrame.codeFrameColumns(
code,
{start: {line: 1, column: 6}},
{highlightCode: true}
)
)
);
});
it('should escape xhtml jsxattribute', () => {
expect(
transform(`
<div id="wôw" />;
<div id="\w" />;
<div id="w &lt; w" />;
`)
).toMatchSnapshot();
});
it('should escape xhtml jsxtext', () => {
/* eslint-disable no-irregular-whitespace */
expect(
transform(`
<div>wow</div>;
<div>wôw</div>;
<div>w & w</div>;
<div>w &amp; w</div>;
<div>w &nbsp; w</div>;
<div>this should not parse as unicode: \u00a0</div>;
<div>this should parse as nbsp:   </div>;
<div>this should parse as unicode: {'\u00a0 '}</div>;
<div>w &lt; w</div>;
`)
).toMatchSnapshot();
/*eslint-enable */
});
it('should handle attributed elements', () => {
expect(
transform(`
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
React.render(<HelloMessage name={
<span>
Sebastian
</span>
} />, mountNode);
`)
).toMatchSnapshot();
});
it('should handle has own property correctly', () => {
expect(
transform(`<hasOwnProperty>testing</hasOwnProperty>;`)
).toMatchSnapshot();
});
it('should have correct comma in nested children', () => {
expect(
transform(`
var x = <div>
<div><br /></div>
<Component>{foo}<br />{bar}</Component>
<br />
</div>;
`)
).toMatchSnapshot();
});
it('should insert commas after expressions before whitespace', () => {
expect(
transform(`
var x =
<div
attr1={
"foo" + "bar"
}
attr2={
"foo" + "bar" +
"baz" + "bug"
}
attr3={
"foo" + "bar" +
"baz" + "bug"
}
attr4="baz">
</div>
`)
).toMatchSnapshot();
});
it('should not add quotes to identifier names', () => {
expect(
transform(`var e = <F aaa new const var default foo-bar/>;`)
).toMatchSnapshot();
});
it('should not strip nbsp even couple with other whitespace', () => {
expect(transform(`<div>&nbsp; </div>;`)).toMatchSnapshot();
});
it('should not strip tags with a single child of nbsp', () => {
expect(transform(`<div>&nbsp;</div>;`)).toMatchSnapshot();
});
it('should properly handle comments between props', () => {
expect(
transform(`
var x = (
<div
/* a multi-line
comment */
attr1="foo">
<span // a double-slash comment
attr2="bar"
/>
</div>
);
`)
).toMatchSnapshot();
});
it('should quote jsx attributes', () => {
expect(
transform(`<button data-value='a value'>Button</button>`)
).toMatchSnapshot();
});
it('should support xml namespaces if flag', () => {
expect(
transform('<f:image n:attr />', {throwIfNamespace: false})
).toMatchSnapshot();
});
it('should throw error namespaces if not flag', () => {
let _error;
const code = `<f:image />`;
try {
transform(code);
} catch (error) {
_error = error;
}
expect(_error).toEqual(
new SyntaxError(
"undefined: Namespace tags are not supported by default. React's " +
"JSX doesn't support namespace tags. You can turn on the " +
"'throwIfNamespace' flag to bypass this warning." +
'\n' +
codeFrame.codeFrameColumns(
code,
{start: {line: 1, column: 2}},
{highlightCode: true}
)
)
);
});
it('should transform known hyphenated tags', () => {
expect(transform(`<font-face />`)).toMatchSnapshot();
});
it('wraps props in react spread for first spread attributes', () => {
expect(transform(`<Component {...x} y={2} z />`)).toMatchSnapshot();
});
it('wraps props in react spread for last spread attributes', () => {
expect(transform(`<Component y={2} z { ... x } />`)).toMatchSnapshot();
});
it('wraps props in react spread for middle spread attributes', () => {
expect(transform(`<Component y={2} { ... x } z />`)).toMatchSnapshot();
});
it('useBuiltIns false uses extend instead of Object.assign', () => {
expect(
transform(`<Component y={2} {...x} />`, {useBuiltIns: false})
).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,504 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable quotes */
'use strict';
const babel = require('@babel/core');
const codeFrame = require('@babel/code-frame');
const {wrap} = require('jest-snapshot-serializer-raw');
function transform(input, options) {
return wrap(
babel.transform(input, {
configFile: false,
plugins: [
'@babel/plugin-syntax-jsx',
'@babel/plugin-transform-arrow-functions',
...(options && options.development
? [
'@babel/plugin-transform-react-jsx-source',
'@babel/plugin-transform-react-jsx-self',
]
: []),
[
'./packages/babel-plugin-react-jsx',
{
useBuiltIns: true,
useCreateElement: false,
...options,
},
],
],
}).code
);
}
describe('transform react to jsx', () => {
it('fragment with no children', () => {
expect(transform(`var x = <></>`)).toMatchSnapshot();
});
it('fragments', () => {
expect(transform(`var x = <><div /></>`)).toMatchSnapshot();
});
it('fragments to set keys', () => {
expect(
transform(`var x = <React.Fragment key="foo"></React.Fragment>`)
).toMatchSnapshot();
});
it('React.fragment to set keys and source', () => {
expect(
transform(`var x = <React.Fragment key='foo'></React.Fragment>`, {
development: true,
})
).toMatchSnapshot();
});
it('fragments in dev mode (no key and source)', () => {
expect(
transform(`var x = <><div /></>`, {
development: true,
})
).toMatchSnapshot();
});
it('nonStatic children', () => {
expect(
transform(
`var x = (
<div>
{[<span key={'0'} />, <span key={'1'} />]}
</div>
);
`,
{
development: true,
}
)
).toMatchSnapshot();
});
it('static children', () => {
expect(
transform(
`var x = (
<div>
<span />
{[<span key={'0'} />, <span key={'1'} />]}
</div>
);
`,
{
development: true,
}
)
).toMatchSnapshot();
});
it('uses jsxDEV instead of jsx in dev mode', () => {
expect(
transform(`var x = <span propOne="one">Hi</span>`, {development: true})
).toMatchSnapshot();
});
it('properly passes in source and self', () => {
expect(
transform(`var x = <div />;`, {development: true})
).toMatchSnapshot();
});
it('should properly handle potentially null variables', () => {
expect(
transform(`
var foo = null;
var x = <div {...foo} />;
`)
).toMatchSnapshot();
});
it('properly handles keys', () => {
expect(
transform(`var x = (
<div>
<div key="1" />
<div key="2" meow="wolf" />
<div key="3" />
</div>
);`)
).toMatchSnapshot();
});
it('uses createElement when the key comes after a spread', () => {
expect(
transform(`var x = (
<div {...props} key="1" foo="bar" />
);`)
).toMatchSnapshot();
});
it('uses jsx when the key comes before a spread', () => {
expect(
transform(`var x = (
<div key="1" {...props} foo="bar" />
);`)
).toMatchSnapshot();
});
it('should properly handle comments adjacent to children', () => {
expect(
transform(`
var x = (
<div>
{/* A comment at the beginning */}
{/* A second comment at the beginning */}
<span>
{/* A nested comment */}
</span>
{/* A sandwiched comment */}
<br />
{/* A comment at the end */}
{/* A second comment at the end */}
</div>
);
`)
).toMatchSnapshot();
});
it('adds appropriate new lines when using spread attribute', () => {
expect(transform(`<Component {...props} sound="moo" />`)).toMatchSnapshot();
});
it('arrow functions', () => {
expect(
transform(`
var foo = function () {
return () => <this />;
};
var bar = function () {
return () => <this.foo />;
};
`)
).toMatchSnapshot();
});
it('assignment', () => {
expect(
transform(`var div = <Component {...props} foo="bar" />`)
).toMatchSnapshot();
});
it('concatenates adjacent string literals', () => {
expect(
transform(`
var x =
<div>
foo
{"bar"}
baz
<div>
buz
bang
</div>
qux
{null}
quack
</div>
`)
).toMatchSnapshot();
});
it('should allow constructor as prop', () => {
expect(transform(`<Component constructor="foo" />;`)).toMatchSnapshot();
});
it('should allow deeper js namespacing', () => {
expect(
transform(`<Namespace.DeepNamespace.Component />;`)
).toMatchSnapshot();
});
it('should allow elements as attributes', () => {
expect(transform(`<div attr=<div /> />`)).toMatchSnapshot();
});
it('should allow js namespacing', () => {
expect(transform(`<Namespace.Component />;`)).toMatchSnapshot();
});
it('should allow nested fragments', () => {
expect(
transform(`
<div>
< >
<>
<span>Hello</span>
<span>world</span>
</>
<>
<span>Goodbye</span>
<span>world</span>
</>
</>
</div>
`)
).toMatchSnapshot();
});
it('should avoid wrapping in extra parens if not needed', () => {
expect(
transform(`
var x = <div>
<Component />
</div>;
var x = <div>
{props.children}
</div>;
var x = <Composite>
{props.children}
</Composite>;
var x = <Composite>
<Composite2 />
</Composite>;
`)
).toMatchSnapshot();
});
it('should convert simple tags', () => {
expect(transform(`var x = <div></div>;`)).toMatchSnapshot();
});
it('should convert simple text', () => {
expect(transform(`var x = <div>text</div>;`)).toMatchSnapshot();
});
it('should disallow spread children', () => {
let _error;
const code = `<div>{...children}</div>;`;
try {
transform(code);
} catch (error) {
_error = error;
}
expect(_error).toEqual(
new SyntaxError(
'undefined: Spread children are not supported in React.' +
'\n' +
codeFrame.codeFrameColumns(
code,
{start: {line: 1, column: 6}},
{highlightCode: true}
)
)
);
});
it('should escape xhtml jsxattribute', () => {
expect(
transform(`
<div id="wôw" />;
<div id="\w" />;
<div id="w &lt; w" />;
`)
).toMatchSnapshot();
});
it('should escape xhtml jsxtext', () => {
/* eslint-disable no-irregular-whitespace */
expect(
transform(`
<div>wow</div>;
<div>wôw</div>;
<div>w & w</div>;
<div>w &amp; w</div>;
<div>w &nbsp; w</div>;
<div>this should not parse as unicode: \u00a0</div>;
<div>this should parse as nbsp:   </div>;
<div>this should parse as unicode: {'\u00a0 '}</div>;
<div>w &lt; w</div>;
`)
).toMatchSnapshot();
/*eslint-enable */
});
it('should handle attributed elements', () => {
expect(
transform(`
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
React.render(<HelloMessage name={
<span>
Sebastian
</span>
} />, mountNode);
`)
).toMatchSnapshot();
});
it('should handle has own property correctly', () => {
expect(
transform(`<hasOwnProperty>testing</hasOwnProperty>;`)
).toMatchSnapshot();
});
it('should have correct comma in nested children', () => {
expect(
transform(`
var x = <div>
<div><br /></div>
<Component>{foo}<br />{bar}</Component>
<br />
</div>;
`)
).toMatchSnapshot();
});
it('should insert commas after expressions before whitespace', () => {
expect(
transform(`
var x =
<div
attr1={
"foo" + "bar"
}
attr2={
"foo" + "bar" +
"baz" + "bug"
}
attr3={
"foo" + "bar" +
"baz" + "bug"
}
attr4="baz">
</div>
`)
).toMatchSnapshot();
});
it('should not add quotes to identifier names', () => {
expect(
transform(`var e = <F aaa new const var default foo-bar/>;`)
).toMatchSnapshot();
});
it('should not strip nbsp even couple with other whitespace', () => {
expect(transform(`<div>&nbsp; </div>;`)).toMatchSnapshot();
});
it('should not strip tags with a single child of nbsp', () => {
expect(transform(`<div>&nbsp;</div>;`)).toMatchSnapshot();
});
it('should properly handle comments between props', () => {
expect(
transform(`
var x = (
<div
/* a multi-line
comment */
attr1="foo">
<span // a double-slash comment
attr2="bar"
/>
</div>
);
`)
).toMatchSnapshot();
});
it('should quote jsx attributes', () => {
expect(
transform(`<button data-value='a value'>Button</button>`)
).toMatchSnapshot();
});
it('should support xml namespaces if flag', () => {
expect(
transform('<f:image n:attr />', {throwIfNamespace: false})
).toMatchSnapshot();
});
it('should throw error namespaces if not flag', () => {
let _error;
const code = `<f:image />`;
try {
transform(code);
} catch (error) {
_error = error;
}
expect(_error).toEqual(
new SyntaxError(
"undefined: Namespace tags are not supported by default. React's " +
"JSX doesn't support namespace tags. You can turn on the " +
"'throwIfNamespace' flag to bypass this warning." +
'\n' +
codeFrame.codeFrameColumns(
code,
{start: {line: 1, column: 2}},
{highlightCode: true}
)
)
);
});
it('should transform known hyphenated tags', () => {
expect(transform(`<font-face />`)).toMatchSnapshot();
});
it('wraps props in react spread for first spread attributes', () => {
expect(transform(`<Component {...x} y={2} z />`)).toMatchSnapshot();
});
it('wraps props in react spread for last spread attributes', () => {
expect(transform(`<Component y={2} z { ... x } />`)).toMatchSnapshot();
});
it('wraps props in react spread for middle spread attributes', () => {
expect(transform(`<Component y={2} { ... x } z />`)).toMatchSnapshot();
});
it('useBuiltIns false uses extend instead of Object.assign', () => {
expect(
transform(`<Component y={2} {...x} />`, {useBuiltIns: false})
).toMatchSnapshot();
});
it('duplicate children prop should transform into sequence expression with actual children', () => {
expect(
transform(`<Component children={1}>2</Component>`)
).toMatchSnapshot();
});
it('duplicate children prop should transform into sequence expression with next prop', () => {
expect(
transform(`<Component children={1} foo={3}>2</Component>`)
).toMatchSnapshot();
});
it('duplicate children props should transform into sequence expression with next prop', () => {
expect(
transform(`<Component children={1} children={4} foo={3}>2</Component>`)
).toMatchSnapshot();
});
it('duplicate children prop should transform into sequence expression with spread', () => {
expect(
transform(`<Component children={1} {...x}>2</Component>`)
).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,213 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`transform react to jsx React.Fragment to set keys and source 1`] = `
var _jsxFileName = "";
var x = React.createElement(React.Fragment, {
key: "foo",
__source: {
fileName: _jsxFileName,
lineNumber: 1
},
__self: this
}, React.createElement("div", {
__source: {
fileName: _jsxFileName,
lineNumber: 1
},
__self: this
}));
`;
exports[`transform react to jsx adds appropriate new lines when using spread attribute 1`] = `
React.createElement(Component, Object.assign({}, props, {
sound: "moo"
}));
`;
exports[`transform react to jsx arrow functions 1`] = `
var foo = function () {
var _this = this;
return function () {
return React.createElement(_this, null);
};
};
var bar = function () {
var _this2 = this;
return function () {
return React.createElement(_this2.foo, null);
};
};
`;
exports[`transform react to jsx assignment 1`] = `
var div = React.createElement(Component, Object.assign({}, props, {
foo: "bar"
}));
`;
exports[`transform react to jsx concatenates adjacent string literals 1`] = `var x = React.createElement("div", null, "foo", "bar", "baz", React.createElement("div", null, "buz bang"), "qux", null, "quack");`;
exports[`transform react to jsx fragment with no children 1`] = `var x = React.createElement(React.Fragment, null);`;
exports[`transform react to jsx normal fragments not to set key and source 1`] = `
var _jsxFileName = "";
var x = React.createElement(React.Fragment, null, React.createElement("div", {
__source: {
fileName: _jsxFileName,
lineNumber: 1
},
__self: this
}));
`;
exports[`transform react to jsx should allow constructor as prop 1`] = `
React.createElement(Component, {
constructor: "foo"
});
`;
exports[`transform react to jsx should allow deeper js namespacing 1`] = `React.createElement(Namespace.DeepNamespace.Component, null);`;
exports[`transform react to jsx should allow elements as attributes 1`] = `
React.createElement("div", {
attr: React.createElement("div", null)
});
`;
exports[`transform react to jsx should allow js namespacing 1`] = `React.createElement(Namespace.Component, null);`;
exports[`transform react to jsx should allow nested fragments 1`] = `React.createElement("div", null, React.createElement(React.Fragment, null, React.createElement(React.Fragment, null, React.createElement("span", null, "Hello"), React.createElement("span", null, "world")), React.createElement(React.Fragment, null, React.createElement("span", null, "Goodbye"), React.createElement("span", null, "world"))));`;
exports[`transform react to jsx should avoid wrapping in extra parens if not needed 1`] = `
var x = React.createElement("div", null, React.createElement(Component, null));
var x = React.createElement("div", null, props.children);
var x = React.createElement(Composite, null, props.children);
var x = React.createElement(Composite, null, React.createElement(Composite2, null));
`;
exports[`transform react to jsx should convert simple tags 1`] = `var x = React.createElement("div", null);`;
exports[`transform react to jsx should convert simple text 1`] = `var x = React.createElement("div", null, "text");`;
exports[`transform react to jsx should escape xhtml jsxattribute 1`] = `
React.createElement("div", {
id: "w\\xF4w"
});
React.createElement("div", {
id: "w"
});
React.createElement("div", {
id: "w < w"
});
`;
exports[`transform react to jsx should escape xhtml jsxtext 1`] = `
React.createElement("div", null, "wow");
React.createElement("div", null, "w\\xF4w");
React.createElement("div", null, "w & w");
React.createElement("div", null, "w & w");
React.createElement("div", null, "w \\xA0 w");
React.createElement("div", null, "this should not parse as unicode: \\xA0");
React.createElement("div", null, "this should parse as nbsp: \\xA0 ");
React.createElement("div", null, "this should parse as unicode: ", '  ');
React.createElement("div", null, "w < w");
`;
exports[`transform react to jsx should handle attributed elements 1`] = `
var HelloMessage = React.createClass({
render: function () {
return React.createElement("div", null, "Hello ", this.props.name);
}
});
React.render(React.createElement(HelloMessage, {
name: React.createElement("span", null, "Sebastian")
}), mountNode);
`;
exports[`transform react to jsx should handle has own property correctly 1`] = `React.createElement("hasOwnProperty", null, "testing");`;
exports[`transform react to jsx should have correct comma in nested children 1`] = `var x = React.createElement("div", null, React.createElement("div", null, React.createElement("br", null)), React.createElement(Component, null, foo, React.createElement("br", null), bar), React.createElement("br", null));`;
exports[`transform react to jsx should insert commas after expressions before whitespace 1`] = `
var x = React.createElement("div", {
attr1: "foo" + "bar",
attr2: "foo" + "bar" + "baz" + "bug",
attr3: "foo" + "bar" + "baz" + "bug",
attr4: "baz"
});
`;
exports[`transform react to jsx should not add quotes to identifier names 1`] = `
var e = React.createElement(F, {
aaa: true,
new: true,
const: true,
var: true,
default: true,
"foo-bar": true
});
`;
exports[`transform react to jsx should not strip nbsp even couple with other whitespace 1`] = `React.createElement("div", null, "\\xA0 ");`;
exports[`transform react to jsx should not strip tags with a single child of nbsp 1`] = `React.createElement("div", null, "\\xA0");`;
exports[`transform react to jsx should properly handle comments adjacent to children 1`] = `var x = React.createElement("div", null, React.createElement("span", null), React.createElement("br", null));`;
exports[`transform react to jsx should properly handle comments between props 1`] = `
var x = React.createElement("div", {
/* a multi-line
comment */
attr1: "foo"
}, React.createElement("span", {
// a double-slash comment
attr2: "bar"
}));
`;
exports[`transform react to jsx should quote jsx attributes 1`] = `
React.createElement("button", {
"data-value": "a value"
}, "Button");
`;
exports[`transform react to jsx should support xml namespaces if flag 1`] = `
React.createElement("f:image", {
"n:attr": true
});
`;
exports[`transform react to jsx should transform known hyphenated tags 1`] = `React.createElement("font-face", null);`;
exports[`transform react to jsx useBuiltIns false uses extend instead of Object.assign 1`] = `
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
React.createElement(Component, _extends({
y: 2
}, x));
`;
exports[`transform react to jsx wraps props in react spread for first spread attributes 1`] = `
React.createElement(Component, Object.assign({}, x, {
y: 2,
z: true
}));
`;
exports[`transform react to jsx wraps props in react spread for last spread attributes 1`] = `
React.createElement(Component, Object.assign({
y: 2,
z: true
}, x));
`;
exports[`transform react to jsx wraps props in react spread for middle spread attributes 1`] = `
React.createElement(Component, Object.assign({
y: 2
}, x, {
z: true
}));
`;

View File

@@ -0,0 +1,400 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`transform react to jsx React.fragment to set keys and source 1`] = `
var _jsxFileName = "";
var x = React.jsxDEV(React.Fragment, {}, "foo", false, {
fileName: _jsxFileName,
lineNumber: 1
}, this);
`;
exports[`transform react to jsx adds appropriate new lines when using spread attribute 1`] = `
React.jsx(Component, Object.assign({}, props, {
sound: "moo"
}));
`;
exports[`transform react to jsx arrow functions 1`] = `
var foo = function () {
var _this = this;
return function () {
return React.jsx(_this, {});
};
};
var bar = function () {
var _this2 = this;
return function () {
return React.jsx(_this2.foo, {});
};
};
`;
exports[`transform react to jsx assignment 1`] = `
var div = React.jsx(Component, Object.assign({}, props, {
foo: "bar"
}));
`;
exports[`transform react to jsx concatenates adjacent string literals 1`] = `
var x = React.jsxs("div", {
children: ["foo", "bar", "baz", React.jsx("div", {
children: "buz bang"
}), "qux", null, "quack"]
});
`;
exports[`transform react to jsx duplicate children prop should transform into sequence expression with actual children 1`] = `
React.jsx(Component, {
children: (1, "2")
});
`;
exports[`transform react to jsx duplicate children prop should transform into sequence expression with next prop 1`] = `
React.jsx(Component, {
foo: (1, 3),
children: "2"
});
`;
exports[`transform react to jsx duplicate children prop should transform into sequence expression with spread 1`] = `
React.jsx(Component, Object.assign({}, (1, x), {
children: "2"
}));
`;
exports[`transform react to jsx duplicate children props should transform into sequence expression with next prop 1`] = `
React.jsx(Component, {
foo: (1, 4, 3),
children: "2"
});
`;
exports[`transform react to jsx fragment with no children 1`] = `var x = React.jsx(React.Fragment, {});`;
exports[`transform react to jsx fragments 1`] = `
var x = React.jsx(React.Fragment, {
children: React.jsx("div", {})
});
`;
exports[`transform react to jsx fragments in dev mode (no key and source) 1`] = `
var _jsxFileName = "";
var x = React.jsxDEV(React.Fragment, {
children: React.jsxDEV("div", {}, undefined, false, {
fileName: _jsxFileName,
lineNumber: 1
}, this)
}, undefined, false);
`;
exports[`transform react to jsx fragments to set keys 1`] = `var x = React.jsx(React.Fragment, {}, "foo");`;
exports[`transform react to jsx nonStatic children 1`] = `
var _jsxFileName = "";
var x = React.jsxDEV("div", {
children: [React.jsxDEV("span", {}, '0', false, {
fileName: _jsxFileName,
lineNumber: 3
}, this), React.jsxDEV("span", {}, '1', false, {
fileName: _jsxFileName,
lineNumber: 3
}, this)]
}, undefined, false, {
fileName: _jsxFileName,
lineNumber: 2
}, this);
`;
exports[`transform react to jsx properly handles keys 1`] = `
var x = React.jsxs("div", {
children: [React.jsx("div", {}, "1"), React.jsx("div", {
meow: "wolf"
}, "2"), React.jsx("div", {}, "3")]
});
`;
exports[`transform react to jsx properly passes in source and self 1`] = `
var _jsxFileName = "";
var x = React.jsxDEV("div", {}, undefined, false, {
fileName: _jsxFileName,
lineNumber: 1
}, this);
`;
exports[`transform react to jsx should allow constructor as prop 1`] = `
React.jsx(Component, {
constructor: "foo"
});
`;
exports[`transform react to jsx should allow deeper js namespacing 1`] = `React.jsx(Namespace.DeepNamespace.Component, {});`;
exports[`transform react to jsx should allow elements as attributes 1`] = `
React.jsx("div", {
attr: React.jsx("div", {})
});
`;
exports[`transform react to jsx should allow js namespacing 1`] = `React.jsx(Namespace.Component, {});`;
exports[`transform react to jsx should allow nested fragments 1`] = `
React.jsx("div", {
children: React.jsxs(React.Fragment, {
children: [React.jsxs(React.Fragment, {
children: [React.jsx("span", {
children: "Hello"
}), React.jsx("span", {
children: "world"
})]
}), React.jsxs(React.Fragment, {
children: [React.jsx("span", {
children: "Goodbye"
}), React.jsx("span", {
children: "world"
})]
})]
})
});
`;
exports[`transform react to jsx should avoid wrapping in extra parens if not needed 1`] = `
var x = React.jsx("div", {
children: React.jsx(Component, {})
});
var x = React.jsx("div", {
children: props.children
});
var x = React.jsx(Composite, {
children: props.children
});
var x = React.jsx(Composite, {
children: React.jsx(Composite2, {})
});
`;
exports[`transform react to jsx should convert simple tags 1`] = `var x = React.jsx("div", {});`;
exports[`transform react to jsx should convert simple text 1`] = `
var x = React.jsx("div", {
children: "text"
});
`;
exports[`transform react to jsx should escape xhtml jsxattribute 1`] = `
React.jsx("div", {
id: "w\\xF4w"
});
React.jsx("div", {
id: "w"
});
React.jsx("div", {
id: "w < w"
});
`;
exports[`transform react to jsx should escape xhtml jsxtext 1`] = `
React.jsx("div", {
children: "wow"
});
React.jsx("div", {
children: "w\\xF4w"
});
React.jsx("div", {
children: "w & w"
});
React.jsx("div", {
children: "w & w"
});
React.jsx("div", {
children: "w \\xA0 w"
});
React.jsx("div", {
children: "this should not parse as unicode: \\xA0"
});
React.jsx("div", {
children: "this should parse as nbsp: \\xA0 "
});
React.jsxs("div", {
children: ["this should parse as unicode: ", '  ']
});
React.jsx("div", {
children: "w < w"
});
`;
exports[`transform react to jsx should handle attributed elements 1`] = `
var HelloMessage = React.createClass({
render: function () {
return React.jsxs("div", {
children: ["Hello ", this.props.name]
});
}
});
React.render(React.jsx(HelloMessage, {
name: React.jsx("span", {
children: "Sebastian"
})
}), mountNode);
`;
exports[`transform react to jsx should handle has own property correctly 1`] = `
React.jsx("hasOwnProperty", {
children: "testing"
});
`;
exports[`transform react to jsx should have correct comma in nested children 1`] = `
var x = React.jsxs("div", {
children: [React.jsx("div", {
children: React.jsx("br", {})
}), React.jsxs(Component, {
children: [foo, React.jsx("br", {}), bar]
}), React.jsx("br", {})]
});
`;
exports[`transform react to jsx should insert commas after expressions before whitespace 1`] = `
var x = React.jsx("div", {
attr1: "foo" + "bar",
attr2: "foo" + "bar" + "baz" + "bug",
attr3: "foo" + "bar" + "baz" + "bug",
attr4: "baz"
});
`;
exports[`transform react to jsx should not add quotes to identifier names 1`] = `
var e = React.jsx(F, {
aaa: true,
new: true,
const: true,
var: true,
default: true,
"foo-bar": true
});
`;
exports[`transform react to jsx should not strip nbsp even couple with other whitespace 1`] = `
React.jsx("div", {
children: "\\xA0 "
});
`;
exports[`transform react to jsx should not strip tags with a single child of nbsp 1`] = `
React.jsx("div", {
children: "\\xA0"
});
`;
exports[`transform react to jsx should properly handle comments adjacent to children 1`] = `
var x = React.jsxs("div", {
children: [React.jsx("span", {}), React.jsx("br", {})]
});
`;
exports[`transform react to jsx should properly handle comments between props 1`] = `
var x = React.jsx("div", {
/* a multi-line
comment */
attr1: "foo",
children: React.jsx("span", {
// a double-slash comment
attr2: "bar"
})
});
`;
exports[`transform react to jsx should properly handle potentially null variables 1`] = `
var foo = null;
var x = React.jsx("div", Object.assign({}, foo));
`;
exports[`transform react to jsx should quote jsx attributes 1`] = `
React.jsx("button", {
"data-value": "a value",
children: "Button"
});
`;
exports[`transform react to jsx should support xml namespaces if flag 1`] = `
React.jsx("f:image", {
"n:attr": true
});
`;
exports[`transform react to jsx should transform known hyphenated tags 1`] = `React.jsx("font-face", {});`;
exports[`transform react to jsx static children 1`] = `
var _jsxFileName = "";
var x = React.jsxDEV("div", {
children: [React.jsxDEV("span", {}, undefined, false, {
fileName: _jsxFileName,
lineNumber: 3
}, this), [React.jsxDEV("span", {}, '0', false, {
fileName: _jsxFileName,
lineNumber: 4
}, this), React.jsxDEV("span", {}, '1', false, {
fileName: _jsxFileName,
lineNumber: 4
}, this)]]
}, undefined, true, {
fileName: _jsxFileName,
lineNumber: 2
}, this);
`;
exports[`transform react to jsx useBuiltIns false uses extend instead of Object.assign 1`] = `
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
React.jsx(Component, _extends({
y: 2
}, x));
`;
exports[`transform react to jsx uses createElement when the key comes after a spread 1`] = `
var x = React.createElement("div", Object.assign({}, props, {
key: "1",
foo: "bar"
}));
`;
exports[`transform react to jsx uses jsx when the key comes before a spread 1`] = `
var x = React.jsx("div", Object.assign({}, props, {
foo: "bar"
}), "1");
`;
exports[`transform react to jsx uses jsxDEV instead of jsx in dev mode 1`] = `
var _jsxFileName = "";
var x = React.jsxDEV("span", {
propOne: "one",
children: "Hi"
}, undefined, false, {
fileName: _jsxFileName,
lineNumber: 1
}, this);
`;
exports[`transform react to jsx wraps props in react spread for first spread attributes 1`] = `
React.jsx(Component, Object.assign({}, x, {
y: 2,
z: true
}));
`;
exports[`transform react to jsx wraps props in react spread for last spread attributes 1`] = `
React.jsx(Component, Object.assign({
y: 2,
z: true
}, x));
`;
exports[`transform react to jsx wraps props in react spread for middle spread attributes 1`] = `
React.jsx(Component, Object.assign({
y: 2
}, x, {
z: true
}));
`;

View File

@@ -0,0 +1,3 @@
'use strict';
module.exports = require('./src/TransformJSXToReactBabelPlugin');

View File

@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-jsx-babel.production.min.js');
} else {
module.exports = require('./cjs/react-jsx-babel.development.js');
}

View File

@@ -0,0 +1,18 @@
{
"name": "babel-plugin-react-jsx",
"version": "0.1.0",
"private": true,
"description": "@babel/plugin-transform-react-jsx",
"main": "index.js",
"dependencies": {
"esutils": "^2.0.0"
},
"files": [
"README.md",
"index.js",
"build-info.json",
"cjs/",
"umd/"
]
}

View File

@@ -0,0 +1,658 @@
// MIT License
// Copyright (c) 2014-present Sebastian McKenzie and other contributors
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// © 2019 GitHub, Inc.
'use strict';
const esutils = require('esutils');
function helper(babel, opts) {
const {types: t} = babel;
const visitor = {};
visitor.JSXNamespacedName = function(path, state) {
const throwIfNamespace =
state.opts.throwIfNamespace === undefined
? true
: !!state.opts.throwIfNamespace;
if (throwIfNamespace) {
throw path.buildCodeFrameError(
`Namespace tags are not supported by default. React's JSX doesn't support namespace tags. \
You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
);
}
};
visitor.JSXSpreadChild = function(path) {
throw path.buildCodeFrameError(
'Spread children are not supported in React.',
);
};
visitor.JSXElement = {
exit(path, file) {
let callExpr;
if (file.opts.useCreateElement || shouldUseCreateElement(path)) {
callExpr = buildCreateElementCall(path, file);
} else {
callExpr = buildJSXElementCall(path, file);
}
if (callExpr) {
path.replaceWith(t.inherits(callExpr, path.node));
}
},
};
visitor.JSXFragment = {
exit(path, file) {
if (opts.compat) {
throw path.buildCodeFrameError(
'Fragment tags are only supported in React 16 and up.',
);
}
let callExpr;
if (file.opts.useCreateElement) {
callExpr = buildCreateElementFragmentCall(path, file);
} else {
callExpr = buildJSXFragmentCall(path, file);
}
if (callExpr) {
path.replaceWith(t.inherits(callExpr, path.node));
}
},
};
return visitor;
function convertJSXIdentifier(node, parent) {
if (t.isJSXIdentifier(node)) {
if (node.name === 'this' && t.isReferenced(node, parent)) {
return t.thisExpression();
} else if (esutils.keyword.isIdentifierNameES6(node.name)) {
node.type = 'Identifier';
} else {
return t.stringLiteral(node.name);
}
} else if (t.isJSXMemberExpression(node)) {
return t.memberExpression(
convertJSXIdentifier(node.object, node),
convertJSXIdentifier(node.property, node),
);
} else if (t.isJSXNamespacedName(node)) {
/**
* If there is flag "throwIfNamespace"
* print XMLNamespace like string literal
*/
return t.stringLiteral(`${node.namespace.name}:${node.name.name}`);
}
return node;
}
function convertAttributeValue(node) {
if (t.isJSXExpressionContainer(node)) {
return node.expression;
} else {
return node;
}
}
function convertAttribute(node, duplicateChildren) {
let value = convertAttributeValue(node.value || t.booleanLiteral(true));
if (t.isStringLiteral(value) && !t.isJSXExpressionContainer(node.value)) {
value.value = value.value.replace(/\n\s+/g, ' ');
// "raw" JSXText should not be used from a StringLiteral because it needs to be escaped.
if (value.extra && value.extra.raw) {
delete value.extra.raw;
}
}
if (duplicateChildren && duplicateChildren.length > 0) {
value = t.sequenceExpression([...duplicateChildren, value]);
}
if (t.isJSXNamespacedName(node.name)) {
node.name = t.stringLiteral(
node.name.namespace.name + ':' + node.name.name.name,
);
} else if (esutils.keyword.isIdentifierNameES6(node.name.name)) {
node.name.type = 'Identifier';
} else {
node.name = t.stringLiteral(node.name.name);
}
return t.inherits(t.objectProperty(node.name, value), node);
}
// We want to use React.createElement, even in the case of
// jsx, for <div {...props} key={key} /> to distinguish it
// from <div key={key} {...props} />. This is an intermediary
// step while we deprecate key spread from props. Afterwards,
// we will remove createElement entirely
function shouldUseCreateElement(path) {
const openingPath = path.get('openingElement');
const attributes = openingPath.node.attributes;
let seenPropsSpread = false;
for (let i = 0; i < attributes.length; i++) {
const attr = attributes[i];
if (
seenPropsSpread &&
t.isJSXAttribute(attr) &&
attr.name.name === 'key'
) {
return true;
} else if (t.isJSXSpreadAttribute(attr)) {
seenPropsSpread = true;
}
}
return false;
}
// Builds JSX into:
// Production: React.jsx(type, arguments, key)
// Development: React.jsxDEV(type, arguments, key, isStaticChildren, source, self)
function buildJSXElementCall(path, file) {
if (opts.filter && !opts.filter(path.node, file)) {
return;
}
const openingPath = path.get('openingElement');
openingPath.parent.children = t.react.buildChildren(openingPath.parent);
const tagExpr = convertJSXIdentifier(
openingPath.node.name,
openingPath.node,
);
const args = [];
let tagName;
if (t.isIdentifier(tagExpr)) {
tagName = tagExpr.name;
} else if (t.isLiteral(tagExpr)) {
tagName = tagExpr.value;
}
const state = {
tagExpr: tagExpr,
tagName: tagName,
args: args,
};
if (opts.pre) {
opts.pre(state, file);
}
let attribs = [];
let key;
let source;
let self;
// for React.jsx, key, __source (dev), and __self (dev) is passed in as
// a separate argument rather than in the args object. We go through the
// props and filter out these three keywords so we can pass them in
// as separate arguments later
for (let i = 0; i < openingPath.node.attributes.length; i++) {
const attr = openingPath.node.attributes[i];
if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
if (attr.name.name === 'key') {
key = convertAttribute(attr).value;
} else if (attr.name.name === '__source') {
source = convertAttribute(attr).value;
} else if (attr.name.name === '__self') {
self = convertAttribute(attr).value;
} else {
attribs.push(attr);
}
} else {
attribs.push(attr);
}
}
if (attribs.length || path.node.children.length) {
attribs = buildJSXOpeningElementAttributes(
attribs,
file,
path.node.children,
);
} else {
// attributes should never be null
attribs = t.objectExpression([]);
}
args.push(attribs);
if (!file.opts.development) {
if (key !== undefined) {
args.push(key);
}
} else {
// isStaticChildren, __source, and __self are only used in development
args.push(
key === undefined ? t.identifier('undefined') : key,
t.booleanLiteral(path.node.children.length > 1),
source === undefined ? t.identifier('undefined') : source,
self === undefined ? t.identifier('undefined') : self,
);
}
if (opts.post) {
opts.post(state, file);
}
return (
state.call ||
t.callExpression(
path.node.children.length > 1 ? state.staticCallee : state.callee,
args,
)
);
}
function isChildrenProp(prop) {
return (
t.isJSXAttribute(prop) &&
t.isJSXIdentifier(prop.name) &&
prop.name.name === 'children'
);
}
// Builds props for React.jsx. This function adds children into the props
// and ensures that props is always an object
function buildJSXOpeningElementAttributes(attribs, file, children) {
let _props = [];
const objs = [];
// In order to avoid having duplicate "children" keys, we avoid
// pushing the "children" prop if we have actual children. However,
// the children prop may have side effects, so to be certain
// these side effects are evaluated, we add them to the following prop
// as a sequence expression to preserve order. So:
// <div children={x++} foo={y}>{child}</div> becomes
// React.jsx('div', {foo: (x++, y), children: child});
// duplicateChildren contains the extra children prop values
let duplicateChildren = [];
const hasChildren = children && children.length > 0;
const useBuiltIns = file.opts.useBuiltIns || false;
if (typeof useBuiltIns !== 'boolean') {
throw new Error(
'transform-react-jsx currently only accepts a boolean option for ' +
'useBuiltIns (defaults to false)',
);
}
while (attribs.length) {
const prop = attribs.shift();
if (hasChildren && isChildrenProp(prop)) {
duplicateChildren.push(convertAttributeValue(prop.value));
} else if (t.isJSXSpreadAttribute(prop)) {
_props = pushProps(_props, objs);
if (duplicateChildren.length > 0) {
objs.push(
t.sequenceExpression([...duplicateChildren, prop.argument]),
);
duplicateChildren = [];
} else {
objs.push(prop.argument);
}
} else {
_props.push(convertAttribute(prop, duplicateChildren));
if (duplicateChildren.length > 0) {
duplicateChildren = [];
}
}
}
// In React.JSX, children is no longer a separate argument, but passed in
// through the argument object
if (hasChildren) {
if (children.length === 1) {
_props.push(
t.objectProperty(
t.identifier('children'),
duplicateChildren.length > 0
? t.sequenceExpression([...duplicateChildren, children[0]])
: children[0],
),
);
} else {
_props.push(
t.objectProperty(
t.identifier('children'),
duplicateChildren.length > 0
? t.sequenceExpression([
...duplicateChildren,
t.arrayExpression(children),
])
: t.arrayExpression(children),
),
);
}
}
pushProps(_props, objs);
if (objs.length === 1) {
// only one object
if (!t.isObjectExpression(objs[0])) {
// if the prop object isn't an object, use Object.assign or _extends
// to ensure that the prop will always be an object (as opposed to a variable
// that could be null at some point)
const expressionHelper = useBuiltIns
? t.memberExpression(t.identifier('Object'), t.identifier('assign'))
: file.addHelper('extends');
attribs = t.callExpression(expressionHelper, [
t.objectExpression([]),
objs[0],
]);
} else {
attribs = objs[0];
}
} else {
// looks like we have multiple objects
if (!t.isObjectExpression(objs[0])) {
objs.unshift(t.objectExpression([]));
}
const expressionHelper = useBuiltIns
? t.memberExpression(t.identifier('Object'), t.identifier('assign'))
: file.addHelper('extends');
// spread it
attribs = t.callExpression(expressionHelper, objs);
}
return attribs;
}
// Builds JSX Fragment <></> into
// Production: React.jsx(type, arguments)
// Development: React.jsxDEV(type, { children})
function buildJSXFragmentCall(path, file) {
if (opts.filter && !opts.filter(path.node, file)) {
return;
}
const openingPath = path.get('openingElement');
openingPath.parent.children = t.react.buildChildren(openingPath.parent);
const args = [];
const tagName = null;
const tagExpr = file.get('jsxFragIdentifier')();
const state = {
tagExpr: tagExpr,
tagName: tagName,
args: args,
};
if (opts.pre) {
opts.pre(state, file);
}
let childrenNode;
if (path.node.children.length > 0) {
if (path.node.children.length === 1) {
childrenNode = path.node.children[0];
} else {
childrenNode = t.arrayExpression(path.node.children);
}
}
args.push(
t.objectExpression(
childrenNode !== undefined
? [t.objectProperty(t.identifier('children'), childrenNode)]
: [],
),
);
if (file.opts.development) {
args.push(
t.identifier('undefined'),
t.booleanLiteral(path.node.children.length > 1),
);
}
if (opts.post) {
opts.post(state, file);
}
return (
state.call ||
t.callExpression(
path.node.children.length > 1 ? state.staticCallee : state.callee,
args,
)
);
}
// Builds JSX into:
// Production: React.createElement(type, arguments, children)
// Development: React.createElement(type, arguments, children, source, self)
function buildCreateElementCall(path, file) {
if (opts.filter && !opts.filter(path.node, file)) {
return;
}
const openingPath = path.get('openingElement');
openingPath.parent.children = t.react.buildChildren(openingPath.parent);
const tagExpr = convertJSXIdentifier(
openingPath.node.name,
openingPath.node,
);
const args = [];
let tagName;
if (t.isIdentifier(tagExpr)) {
tagName = tagExpr.name;
} else if (t.isLiteral(tagExpr)) {
tagName = tagExpr.value;
}
const state = {
tagExpr: tagExpr,
tagName: tagName,
args: args,
};
if (opts.pre) {
opts.pre(state, file);
}
let attribs = openingPath.node.attributes;
if (attribs.length) {
attribs = buildCreateElementOpeningElementAttributes(attribs, file);
} else {
attribs = t.nullLiteral();
}
args.push(attribs, ...path.node.children);
if (opts.post) {
opts.post(state, file);
}
return state.call || t.callExpression(state.oldCallee, args);
}
function pushProps(_props, objs) {
if (!_props.length) {
return _props;
}
objs.push(t.objectExpression(_props));
return [];
}
/**
* The logic for this is quite terse. It's because we need to
* support spread elements. We loop over all attributes,
* breaking on spreads, we then push a new object containing
* all prior attributes to an array for later processing.
*/
function buildCreateElementOpeningElementAttributes(attribs, file) {
let _props = [];
const objs = [];
const useBuiltIns = file.opts.useBuiltIns || false;
if (typeof useBuiltIns !== 'boolean') {
throw new Error(
'transform-react-jsx currently only accepts a boolean option for ' +
'useBuiltIns (defaults to false)',
);
}
while (attribs.length) {
const prop = attribs.shift();
if (t.isJSXSpreadAttribute(prop)) {
_props = pushProps(_props, objs);
objs.push(prop.argument);
} else {
const attr = convertAttribute(prop);
_props.push(attr);
}
}
pushProps(_props, objs);
if (objs.length === 1) {
// only one object
attribs = objs[0];
} else {
// looks like we have multiple objects
if (!t.isObjectExpression(objs[0])) {
objs.unshift(t.objectExpression([]));
}
const expressionHelper = useBuiltIns
? t.memberExpression(t.identifier('Object'), t.identifier('assign'))
: file.addHelper('extends');
// spread it
attribs = t.callExpression(expressionHelper, objs);
}
return attribs;
}
function buildCreateElementFragmentCall(path, file) {
if (opts.filter && !opts.filter(path.node, file)) {
return;
}
const openingPath = path.get('openingElement');
openingPath.parent.children = t.react.buildChildren(openingPath.parent);
const args = [];
const tagName = null;
const tagExpr = file.get('jsxFragIdentifier')();
const state = {
tagExpr: tagExpr,
tagName: tagName,
args: args,
};
if (opts.pre) {
opts.pre(state, file);
}
// no attributes are allowed with <> syntax
args.push(t.nullLiteral(), ...path.node.children);
if (opts.post) {
opts.post(state, file);
}
return state.call || t.callExpression(state.oldCallee, args);
}
}
module.exports = function(babel) {
const {types: t} = babel;
const createIdentifierParser = id => () => {
return id
.split('.')
.map(name => t.identifier(name))
.reduce((object, property) => t.memberExpression(object, property));
};
const visitor = helper(babel, {
pre(state) {
const tagName = state.tagName;
const args = state.args;
if (t.react.isCompatTag(tagName)) {
args.push(t.stringLiteral(tagName));
} else {
args.push(state.tagExpr);
}
},
post(state, pass) {
state.callee = pass.get('jsxIdentifier')();
state.staticCallee = pass.get('jsxStaticIdentifier')();
state.oldCallee = pass.get('oldJSXIdentifier')();
},
});
visitor.Program = {
enter(path, state) {
state.set(
'oldJSXIdentifier',
createIdentifierParser('React.createElement'),
);
state.set(
'jsxIdentifier',
createIdentifierParser(
state.opts.development ? 'React.jsxDEV' : 'React.jsx',
),
);
state.set(
'jsxStaticIdentifier',
createIdentifierParser(
state.opts.development ? 'React.jsxDEV' : 'React.jsxs',
),
);
state.set('jsxFragIdentifier', createIdentifierParser('React.Fragment'));
},
};
visitor.JSXAttribute = function(path) {
if (t.isJSXElement(path.node.value)) {
path.node.value = t.jsxExpressionContainer(path.node.value);
}
};
return {
name: 'transform-react-jsx',
visitor,
};
};

View File

@@ -1,7 +1,7 @@
{
"name": "create-subscription",
"description": "utility for subscribing to external data sources inside React components",
"version": "16.8.2",
"version": "16.10.2",
"repository": {
"type": "git",
"url": "https://github.com/facebook/react.git",

View File

@@ -14,6 +14,7 @@ let BehaviorSubject;
let ReactFeatureFlags;
let React;
let ReactNoop;
let Scheduler;
let ReplaySubject;
describe('createSubscription', () => {
@@ -24,6 +25,7 @@ describe('createSubscription', () => {
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
React = require('react');
ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler');
BehaviorSubject = require('rxjs/BehaviorSubject').BehaviorSubject;
ReplaySubject = require('rxjs/ReplaySubject').ReplaySubject;
@@ -58,23 +60,23 @@ describe('createSubscription', () => {
ReactNoop.render(
<Subscription source={observable}>
{(value = 'default') => {
ReactNoop.yield(value);
Scheduler.unstable_yieldValue(value);
return null;
}}
</Subscription>,
);
// Updates while subscribed should re-render the child component
expect(ReactNoop.flush()).toEqual(['default']);
expect(Scheduler).toFlushAndYield(['default']);
observable.next(123);
expect(ReactNoop.flush()).toEqual([123]);
expect(Scheduler).toFlushAndYield([123]);
observable.next('abc');
expect(ReactNoop.flush()).toEqual(['abc']);
expect(Scheduler).toFlushAndYield(['abc']);
// Unmounting the subscriber should remove listeners
ReactNoop.render(<div />);
observable.next(456);
expect(ReactNoop.flush()).toEqual([]);
expect(Scheduler).toFlushAndYield([]);
});
it('should support observable types like RxJS ReplaySubject', () => {
@@ -95,20 +97,20 @@ describe('createSubscription', () => {
});
function render(value = 'default') {
ReactNoop.yield(value);
Scheduler.unstable_yieldValue(value);
return null;
}
const observable = createReplaySubject('initial');
ReactNoop.render(<Subscription source={observable}>{render}</Subscription>);
expect(ReactNoop.flush()).toEqual(['initial']);
expect(Scheduler).toFlushAndYield(['initial']);
observable.next('updated');
expect(ReactNoop.flush()).toEqual(['updated']);
expect(Scheduler).toFlushAndYield(['updated']);
// Unsetting the subscriber prop should reset subscribed values
ReactNoop.render(<Subscription>{render}</Subscription>);
expect(ReactNoop.flush()).toEqual(['default']);
expect(Scheduler).toFlushAndYield(['default']);
});
describe('Promises', () => {
@@ -124,9 +126,9 @@ describe('createSubscription', () => {
function render(hasLoaded) {
if (hasLoaded === undefined) {
ReactNoop.yield('loading');
Scheduler.unstable_yieldValue('loading');
} else {
ReactNoop.yield(hasLoaded ? 'finished' : 'failed');
Scheduler.unstable_yieldValue(hasLoaded ? 'finished' : 'failed');
}
return null;
}
@@ -141,19 +143,19 @@ describe('createSubscription', () => {
// Test a promise that resolves after render
ReactNoop.render(<Subscription source={promiseA}>{render}</Subscription>);
expect(ReactNoop.flush()).toEqual(['loading']);
expect(Scheduler).toFlushAndYield(['loading']);
resolveA(true);
await promiseA;
expect(ReactNoop.flush()).toEqual(['finished']);
expect(Scheduler).toFlushAndYield(['finished']);
// Test a promise that resolves before render
// Note that this will require an extra render anyway,
// Because there is no way to synchronously get a Promise's value
rejectB(false);
ReactNoop.render(<Subscription source={promiseB}>{render}</Subscription>);
expect(ReactNoop.flush()).toEqual(['loading']);
expect(Scheduler).toFlushAndYield(['loading']);
await promiseB.catch(() => true);
expect(ReactNoop.flush()).toEqual(['failed']);
expect(Scheduler).toFlushAndYield(['failed']);
});
it('should still work if unsubscription is managed incorrectly', async () => {
@@ -167,7 +169,7 @@ describe('createSubscription', () => {
});
function render(value = 'default') {
ReactNoop.yield(value);
Scheduler.unstable_yieldValue(value);
return null;
}
@@ -177,9 +179,9 @@ describe('createSubscription', () => {
// Subscribe first to Promise A then Promise B
ReactNoop.render(<Subscription source={promiseA}>{render}</Subscription>);
expect(ReactNoop.flush()).toEqual(['default']);
expect(Scheduler).toFlushAndYield(['default']);
ReactNoop.render(<Subscription source={promiseB}>{render}</Subscription>);
expect(ReactNoop.flush()).toEqual(['default']);
expect(Scheduler).toFlushAndYield(['default']);
// Resolve both Promises
resolveB(123);
@@ -187,7 +189,7 @@ describe('createSubscription', () => {
await Promise.all([promiseA, promiseB]);
// Ensure that only Promise B causes an update
expect(ReactNoop.flush()).toEqual([123]);
expect(Scheduler).toFlushAndYield([123]);
});
it('should not call setState for a Promise that resolves after unmount', async () => {
@@ -201,7 +203,7 @@ describe('createSubscription', () => {
});
function render(hasLoaded) {
ReactNoop.yield('rendered');
Scheduler.unstable_yieldValue('rendered');
return null;
}
@@ -211,11 +213,11 @@ describe('createSubscription', () => {
});
ReactNoop.render(<Subscription source={promise}>{render}</Subscription>);
expect(ReactNoop.flush()).toEqual(['rendered']);
expect(Scheduler).toFlushAndYield(['rendered']);
// Unmount
ReactNoop.render(null);
ReactNoop.flush();
expect(Scheduler).toFlushWithoutYielding();
// Resolve Promise should not trigger a setState warning
resolvePromise(true);
@@ -233,7 +235,7 @@ describe('createSubscription', () => {
});
function render(value = 'default') {
ReactNoop.yield(value);
Scheduler.unstable_yieldValue(value);
return null;
}
@@ -245,28 +247,28 @@ describe('createSubscription', () => {
);
// Updates while subscribed should re-render the child component
expect(ReactNoop.flush()).toEqual(['a-0']);
expect(Scheduler).toFlushAndYield(['a-0']);
// Unsetting the subscriber prop should reset subscribed values
ReactNoop.render(
<Subscription source={observableB}>{render}</Subscription>,
);
expect(ReactNoop.flush()).toEqual(['b-0']);
expect(Scheduler).toFlushAndYield(['b-0']);
// Updates to the old subscribable should not re-render the child component
observableA.next('a-1');
expect(ReactNoop.flush()).toEqual([]);
expect(Scheduler).toFlushAndYield([]);
// Updates to the bew subscribable should re-render the child component
observableB.next('b-1');
expect(ReactNoop.flush()).toEqual(['b-1']);
expect(Scheduler).toFlushAndYield(['b-1']);
});
it('should ignore values emitted by a new subscribable until the commit phase', () => {
const log = [];
function Child({value}) {
ReactNoop.yield('Child: ' + value);
Scheduler.unstable_yieldValue('Child: ' + value);
return null;
}
@@ -303,7 +305,7 @@ describe('createSubscription', () => {
return (
<Subscription source={this.state.observed}>
{(value = 'default') => {
ReactNoop.yield('Subscriber: ' + value);
Scheduler.unstable_yieldValue('Subscriber: ' + value);
return <Child value={value} />;
}}
</Subscription>
@@ -315,12 +317,12 @@ describe('createSubscription', () => {
const observableB = createBehaviorSubject('b-0');
ReactNoop.render(<Parent observed={observableA} />);
expect(ReactNoop.flush()).toEqual(['Subscriber: a-0', 'Child: a-0']);
expect(Scheduler).toFlushAndYield(['Subscriber: a-0', 'Child: a-0']);
expect(log).toEqual(['Parent.componentDidMount']);
// Start React update, but don't finish
ReactNoop.render(<Parent observed={observableB} />);
ReactNoop.flushThrough(['Subscriber: b-0']);
expect(Scheduler).toFlushAndYieldThrough(['Subscriber: b-0']);
expect(log).toEqual(['Parent.componentDidMount']);
// Emit some updates from the uncommitted subscribable
@@ -335,7 +337,7 @@ describe('createSubscription', () => {
// We expect the last emitted update to be rendered (because of the commit phase value check)
// But the intermediate ones should be ignored,
// And the final rendered output should be the higher-priority observable.
expect(ReactNoop.flush()).toEqual([
expect(Scheduler).toFlushAndYield([
'Child: b-0',
'Subscriber: b-3',
'Child: b-3',
@@ -353,7 +355,7 @@ describe('createSubscription', () => {
const log = [];
function Child({value}) {
ReactNoop.yield('Child: ' + value);
Scheduler.unstable_yieldValue('Child: ' + value);
return null;
}
@@ -390,7 +392,7 @@ describe('createSubscription', () => {
return (
<Subscription source={this.state.observed}>
{(value = 'default') => {
ReactNoop.yield('Subscriber: ' + value);
Scheduler.unstable_yieldValue('Subscriber: ' + value);
return <Child value={value} />;
}}
</Subscription>
@@ -402,12 +404,12 @@ describe('createSubscription', () => {
const observableB = createBehaviorSubject('b-0');
ReactNoop.render(<Parent observed={observableA} />);
expect(ReactNoop.flush()).toEqual(['Subscriber: a-0', 'Child: a-0']);
expect(Scheduler).toFlushAndYield(['Subscriber: a-0', 'Child: a-0']);
expect(log).toEqual(['Parent.componentDidMount']);
// Start React update, but don't finish
ReactNoop.render(<Parent observed={observableB} />);
ReactNoop.flushThrough(['Subscriber: b-0']);
expect(Scheduler).toFlushAndYieldThrough(['Subscriber: b-0']);
expect(log).toEqual(['Parent.componentDidMount']);
// Emit some updates from the old subscribable
@@ -420,7 +422,7 @@ describe('createSubscription', () => {
// Flush everything and ensure that the correct subscribable is used
// We expect the new subscribable to finish rendering,
// But then the updated values from the old subscribable should be used.
expect(ReactNoop.flush()).toEqual([
expect(Scheduler).toFlushAndYield([
'Child: b-0',
'Subscriber: a-2',
'Child: a-2',
@@ -433,7 +435,7 @@ describe('createSubscription', () => {
// Updates from the new subscribable should be ignored.
observableB.next('b-1');
expect(ReactNoop.flush()).toEqual([]);
expect(Scheduler).toFlushAndYield([]);
expect(log).toEqual([
'Parent.componentDidMount',
'Parent.componentDidUpdate',
@@ -479,7 +481,7 @@ describe('createSubscription', () => {
<Subscription source={observable}>{value => null}</Subscription>,
);
expect(ReactNoop.flush).toThrow(
expect(Scheduler).toFlushAndThrow(
'A subscription must return an unsubscribe function.',
);
});

View File

@@ -28,7 +28,8 @@ Then add it to your ESLint configuration:
],
"rules": {
// ...
"react-hooks/rules-of-hooks": "error"
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
}
```
@@ -37,6 +38,8 @@ Then add it to your ESLint configuration:
Please refer to the [Rules of Hooks](https://reactjs.org/docs/hooks-rules.html) documentation and the [Hooks FAQ](https://reactjs.org/docs/hooks-faq.html#what-exactly-do-the-lint-rules-enforce) to learn more about this rule.
For feedback about the `exhaustive-deps` rule, please post in [this thread](https://github.com/facebook/react/issues/14920).
## License
MIT

Some files were not shown because too many files have changed in this diff Show More