* Split performWork into renderRoot and commitRoot
It turns out that the scheduler is too coupled to how the DOM renderer
works. Specifically, the requestIdleCallback model, and how roots are
committed immediately after completing. Other renderers have different
constraints for when to yield and when to commit work.
We're moving towards a model where the scheduler only works on a single
root at a time, and the render phase and commit phase are split into
distinct entry points. This gives the renderer more control over when
roots are committed, coordinating multiple roots, deferring the commit
phase, batching updates, when to yield execution, and so on.
In this initial commit, I've left the renderers alone and only changed
the scheduler. Mostly, this involved extracting logic related to
multiple roots and moving it into its own section at the bottom of the
file. The idea is that this section can be lifted pretty much as-is
into the renderers. I'll do that next.
* Remove FiberRoot scheduleAt
Isn't actually used anywhere
* Make the root schedule a linked list again
Since this still lives inside the renderer, let's just use the
FiberRoot type. The FiberRoot concept will likely be lifted out
eventually, anyway.
* commitRoot should accept a HostRoot
This way it's less reliant on the alternate model
* Unify branches
* Remove dead branch
onUncaughtError is only called while we're working on a root.
* remainingWork -> remainingExpirationTime
I was wary of leaking NoWork but mixing numbers and null is worse so
let's just do it until we think of something better.
* Rename stuff
* react-dom/src/syntheticEvents => events, and put plugins into it
* Flatten react-dom/src/shared
* Split react-dom/src/client/utils into event/ and root client folder
Makes it clearer what is used by what.
* Strictly separate modules that can be imported by client and server
* shared/src -> shared
It's not a real package and doesn't even have package.json.
This will also make importing less weird if we drop Haste.
* Get rid of shared/utils
Moved event-specific into shared/event.
Moved rest to the root since distinction has always been pretty arbitrary.
* Fix references to old shared/src paths
* Move files and tests to more meaningful places
* Fix the build
Now that we import reconciler via react-reconciler, I needed to make a few tweaks.
* Update sizes
* Move @preventMunge directive to FB header
* Revert unintentional change
* Fix Flow coverage
I forgot to @flow-ify those files. This uncovered some issues.
* Prettier, I love you but you're bringing me down
Prettier, I love you but you're bringing me down
Like a rat in a cage
Pulling minimum wage
Prettier, I love you but you're bringing me down
Prettier, you're safer and you're wasting my time
Our records all show you were filthy but fine
But they shuttered your stores
When you opened the doors
To the cops who were bored once they'd run out of crime
Prettier, you're perfect, oh, please don't change a thing
Your mild billionaire mayor's now convinced he's a king
So the boring collect
I mean all disrespect
In the neighborhood bars I'd once dreamt I would drink
Prettier, I love you but you're freaking me out
There's a ton of the twist but we're fresh out of shout
Like a death in the hall
That you hear through your wall
Prettier, I love you but you're freaking me out
Prettier, I love you but you're bringing me down
Prettier, I love you but you're bringing me down
Like a death of the heart
Jesus, where do I start?
But you're still the one pool where I'd happily drown
And oh! Take me off your mailing list
For kids who think it still exists
Yes, for those who think it still exists
Maybe I'm wrong and maybe you're right
Maybe I'm wrong and maybe you're right
Maybe you're right, maybe I'm wrong
And just maybe you're right
And oh! Maybe mother told you true
And there'll always be somebody there for you
And you'll never be alone
But maybe she's wrong and maybe I'm right
And just maybe she's wrong
Maybe she's wrong and maybe I'm right
And if so, here's this song!
* Include component stack in more places, including SSR
* Forbid including reconciler code into the server bundle
* Tighten up the Flow annotation
* Fix lint
* Gosh Prettier
* Only renderers should depend on reconciler code
* Remove react-art dependency on react-dom modules
They share ReactDOMFrameScheduling so I moved it to shared.
* Update build size
* [CS] Clone container instead of new root concept
The extra "root" concept is kind of unnecessary. Instead of having a
mutable container even in the persistent mode, I'll instead make the
container be immutable too and be cloned. Then the "commit" just becomes
swapping the previous container for the new one.
* Change the signature or persistence again
We may need to clone without any updates, e.g. when the children are changed.
Passing in the previous node is not enough to recycle since it won't have the
up-to-date props and children. It's really only useful to for allocation pooling.
* Implement persistent updates
This forks the update path for host fibers. For mutation mode we mark
them as having an effect. For persistence mode, we clone the stateNode with
new props/children.
Next I'll do HostRoot and HostPortal.
* Refine protocol into a complete and commit phase
finalizeContainerChildren will get called at the complete phase.
replaceContainer will get called at commit.
Also, drop the keepChildren flag. We'll never keep children as we'll never
update a container if none of the children has changed.
* Implement persistent updates of roots and portals
These are both "containers". Normally we rely on placement/deletion effects
to deal with insertions into the containers. In the persistent mode we need
to clone the container and append all the changed children to it.
I needed somewhere to store these new containers before they're committed
so I added another field.
* Commit persistent work at the end by swapping out the container
* Unify cloneOrRecycle
Originally I tried to make the recyclable instance nullable but Flow didn't
like that and it's kind of sketchy since the instance type might not be
nullable.
However, the real difference which one we call is depending on whether they
are equal. We can just offload that to the renderer. Most of them won't
need to know about this at all since they'll always clone or just create
new.
The ones that do know now have to be careful to compare them so they don't
reuse an existing instance but that's probably fine to simplify the
implementation and API.
* Add persistent noop renderer for testing
* Add basic persistent tree test
* Test bail out
This adds a test for bailouts. This revealed a subtle bug. We don't set the
return pointer when stepping into newly created fibers because there
can only be one. However, since I'm reusing this mechanism for persistent
updates, I'll need to set the return pointer because a bailed out tree
won't have the right return pointer.
* Test persistent text nodes
Found another bug.
* Add persistent portal test
This creates a bit of an unfortunate feature testing in the unmount
branch.
That's because we want to trigger nested host deletions in portals in the
mutation mode.
* Don't consider container when determining portal identity
Basically, we can't use the container to determine if we should keep
identity and update an existing portal instead of recreate it. Because
for persistent containers, there is no permanent identity.
This makes it kind of strange to even use portals in this mode. It's
probably more ideal to have another concept that has permanent identity
rather than trying to swap out containers.
* Clear portals when the portal is deleted
When a portal gets deleted we need to create a new empty container and
replace the current one with the empty one.
* Add renderer mode flags for dead code elimination
* Simplify ReactNoop fix
* Add new type to the host config for persistent configs
We need container to stay as the persistent identity of the root atom.
So that we can refer to portals over time.
Instead, I'll introduce a new type just to temporarily hold the children
of a container until they're ready to be committed into the permanent
container. Essentially, this is just a fancy array that is not an array
so that the host can choose data structure/allocation for it.
* Implement new hooks
Now containers are singletons and instead their children swap. That way
portals can use the container as part of their identity again.
* Update build size and error codes
* Address comment
* Move new files to new location
* Enable Yarn workspaces for packages/*
* Move src/isomorphic/* into packages/react/src/*
* Create index.js stubs for all packages in packages/*
This makes the test pass again, but breaks the build because npm/ folders aren't used yet.
I'm not sure if we'll keep this structure--I'll just keep working and fix the build after it settles down.
* Put FB entry point for react-dom into packages/*
* Move src/renderers/testing/* into packages/react-test-renderer/src/*
Note that this is currently broken because Jest ignores node_modules,
and so Yarn linking makes Jest skip React source when transforming.
* Remove src/node_modules
It is now unnecessary. Some tests fail though.
* Add a hacky workaround for Jest/Workspaces issue
Jest sees node_modules and thinks it's third party code.
This is a hacky way to teach Jest to still transform anything in node_modules/react*
if it resolves outside of node_modules (such as to our packages/*) folder.
I'm not very happy with this and we should revisit.
* Add a fake react-native package
* Move src/renderers/art/* into packages/react-art/src/*
* Move src/renderers/noop/* into packages/react-noop-renderer/src/*
* Move src/renderers/dom/* into packages/react-dom/src/*
* Move src/renderers/shared/fiber/* into packages/react-reconciler/src/*
* Move DOM/reconciler tests I previously forgot to move
* Move src/renderers/native-*/* into packages/react-native-*/src/*
* Move shared code into packages/shared
It's not super clear how to organize this properly yet.
* Add back files that somehow got lost
* Fix the build
* Prettier
* Add missing license headers
* Fix an issue that caused mocks to get included into build
* Update other references to src/
* Re-run Prettier
* Fix lint
* Fix weird Flow violation
I didn't change this file but Flow started complaining.
Caleb said this annotation was unnecessarily using $Abstract though so I removed it.
* Update sizes
* Fix stats script
* Fix packaging fixtures
Use file: instead of NODE_PATH since NODE_PATH.
NODE_PATH trick only worked because we had no react/react-dom in root node_modules, but now we do.
file: dependency only works as I expect in Yarn, so I moved the packaging fixtures to use Yarn and committed lockfiles.
Verified that the page shows up.
* Fix art fixture
* Fix reconciler fixture
* Fix SSR fixture
* Rename native packages
* Initial commit of react-reconciler bundle
* I think it’s working 🙀
* React reconciler: slightly better description and README
* Drop react-reconciler version to an unstable release number
* Convert to moduleType enum and fix packaging
* eslint
* s/Renderer/Reconciler in docs
* yarn prettier
* change names of things in the react-reconciler readme
* change predicate
* rollup: flip object-assign shimming check
* copy noop renderer into react-reconciler fixture
* Change reconciler fixture test
* prettier
* Remove a bunch of Noop test renderer
* Delete a bunch of stuff we don’t care about for reconciler teesting. Add flow pragmas for future flow pragma testing
* Remove PATENTS
* Update Reconciler fixture docs
* ReactDOMUnstableNativeDependencies should be ISOMORPHIC
* Inline fixture renderer
* Make it "RENDERER"
* There is no UMD build. It also doesn't need propTypes.
* Tweak how the reconciler is built
* Record sizes
* Update README.md
Did find and replace in TextMate.
```
find: (?:( \*)( ))?Copyright (?:\(c\) )?(\d{4})\b.+Facebook[\s\S]+(?:this source tree|the same directory)\.$
replace: $1$2Copyright (c) $3-present, Facebook, Inc.\n$1\n$1$2This source code is licensed under the MIT license found in the\n$1$2LICENSE file in the root directory of this source tree.
```
NOTE: This commit is not exactly what went out as RC2 because I forgot to push. See tag v16.0.0-rc.2 (d06680ea9e) instead. Bumping the version here so we're at the right place though.
* Import react-art/lib/{Circle,Rectangle,Wedge}.art
Copied from react-art@0.15.1 built files.
* Changes to built files to make ART shapes work
Test Plan: Opened the fixture. React logo shows up with its normal dot, now rendered by a `<Circle />`.
* Throw error to warn of mistaken loading of prod + dev React bundles
**what is the change?:**
Credit to @gaearon for coming up with a clever way to check for this. :)
I mainly just did the manual testing and fixed a couple of typos in his
idea.
I'd like to do a follow-up PR to add a link and a page explaining this
issue more and suggesting how to fix it.
**why make this change?:**
We want to warn for an unfortunate gotcha for
the following situation -
1. Wanting to shrink their JS bundle, an engineer runs it through
'uglifyjs' or some other minifier. They assume this will also do
dead-code-elimination, but the 'prod' and 'dev' checks are not
envified yet and dev-only code does not get removed.
2. Then they run it through browserify's 'envify' or some other tool to
change all calls to 'process.env.NODE_ENV' to "production". This
makes their code ready to ship, except the 'dev' only dead code is
still in the bundle. Their bundle is twice as large as it needs to
be, due to the dead code.
This was a problem with the old build system before, but with our new
build system output it's possible to detect and throw an informative
error in this case.
**test plan:**
1. run the build in react as usual; `yarn build`
2. manually run 'uglifyjs -mt' on 'build/packages/react/index.js' to
simulate mistakenly minifying React before env variables are
resolved, which skips dead code elimination.
3. run the fixtures build - `cd fixtures/packaging && node
./build-all.js && serve ../..`
4. Visit just the production browserify fixture -
http://localhost:5000/fixtures/packaging/browserify/prod/
5. You should see the error thrown indicating this problem has occurred.
(Flarnie will insert a screenshot)
6. Do the above steps with NO uglifyjs step, and verify that no error is
thrown. When there is no minification applied, we don't assume that
this mix-up has occurred.
(Flarnie will insert a screenshot)
**issue:**
fixes#9589
* Remove extra 'prod' env. check and add link to docs in error message
**what is the change?:**
Based on helpful feedback from @gaearon
- removed outer check that `process.env.NODE_ENV` is "production" since
we are only calling the `testMinification` method inside of another
check for "production" environment.
- Added an fburl that points to [our current docs on using the production version of React](https://facebook.github.io/react/docs/optimizing-performance.html#use-the-production-build)
**why make this change?:**
To save an extra layer of conditionals and to make the error message
more clear.
**test plan:**
Same test plan as earlier -
1. run the build in react as usual; yarn build
2. manually run 'uglifyjs -mt' on 'build/packages/react/index.js' to
simulate mistakenly minifying React before env variables are
resolved, which skips dead code elimination.
3. run the fixtures build - cd fixtures/packaging && node ./build-all.js && serve ../..
4. Visit just the production browserify fixture -
http://localhost:5000/fixtures/packaging/browserify/prod/
You should see the error thrown indicating this problem has occurred.
(Flarnie will insert a screenshot in comments on the PR)
6. Do the above steps with NO uglifyjs step, and verify that no error is thrown. When there is no minification applied, we don't assume that this mix-up has occurred.
(Flarnie will insert a screenshot in the comments on the PR.)
**issue:**
https://github.com/facebook/react/issues/9589
* WIP fix and test 'testMinificationUsedDCE' method
**what is the change?:**
- Instead of looking for one match when having the method inspect it's
own source, we look for two matches, because the search itself will be
a match.
- WIP moving this method into another file and testing it.
Next steps:
- Figure out why the babel.transform call is not actually minifying the
code
- Add tests for uglifyjs
- Update build process so that this file can be accessed from
`packages/react/index.js`
**why make this change?:**
- We had a bug in the 'testMinification' method, and I thought the name
could be more clear. I fixed the code and also changed the name.
- In order to avoid other bugs and keep this code working in the future
we'd like to add a unit test for this method. Using the npm modules
for 'uglifyjs' and 'babel'/'babili' we should be able to actually test
how this method will work when minified with different configurations.
**test plan:**
`yarn test`
**issue:**
https://github.com/facebook/react/issues/9589
* Add babeli and uglifyjs as dev-only dependencies
**what is the change?:**
See commit title
**why make this change?:**
In order to test that we are correctly detecting different minification
situations, we are using these modules in a test.
**test plan:**
NA
**issue:**
https://github.com/facebook/react/issues/9589
* Fix typo and add 'uglifyjs' tests
**what is the change?:**
There was a mix-up in the conditional in 'testMinificationUsedDCE' and
this fixes it.
The great new tests we added caught the typo. :)
Next steps:
- get the tests for 'babili' working
- update build scripts so that this the 'testMinificationUsedDCE'
module is available from 'packages/react/index.js'
**why make this change?:**
We want to modularize 'testMinificationUsedDCE' and test it.
This verifies that the method warns when `uglifyjs` is used to minify
but dead code elimination is not done, in a production environment.
Generally this is a 'gotcha' which we want to warn folks aboug.
**test plan:**
`yarn test src/shared/utils/__tests__/testMinificationUsedDCE-test.js`
**issue:**
https://github.com/facebook/react/issues/9589
* Run prettier
* var -> const/let
* Require specific version of `uglify-js`
**what is the change?:**
Removed the '^' from the npm package requirement
**why make this change?:**
I am seeing failures in CI that show `uglify-js` is returning different
output there from my local environment. To further debug this I'd like
to run CI with the exact same version of `uglify-js` that I am using
locally.
**test plan:**
push and see what CI does
**issue:**
https://github.com/facebook/react/issues/9589
* Add build step copying testMinificationUsedDCE into build/packages/react/cj
**what is the change?:**
This is a first step - we still need (I think) to process this file to
get it's contents wrapped in an 'iffe'.
Added a step to the build script which copies the source file for the
'testMinificationUsedDCE' module into the 'cjs' directory of our react
package build.
**why make this change?:**
We want this module to be available to the 'index.js' module in this
build.
**test plan:**
Will do manual testing once the build stuff is fully set up.
**issue:**
* Inline 'testMinificationUsedDCE' and remove unit test for now
What:
- Inlines the 'testMinificationUsedDCE' method into
'packages/react/index.js'
- Removes unit test for 'testMinififcationUsedDCE'
- Puts dependencies back the way that they were; should remove extra
dependencies that were added for the unit test.
Why:
- It would add complexity to the build process to add another file to
the 'build/packages/react/cjs' folder, and that is the only way to
pull this out and test it. So instead we are inlining this.
* Revert unintentional changes to dependency versions, variable placing
**what is the change?:**
- We had updated and added some dependencies, but ended up reverting
this in a previous commit. The `yarn.lock` and `package.json` needed
updated still though.
- There is a call to `Function.toString` which we wanted to wrap in a
`try/catch` block.
**why make this change?:**
To remove unrelated dependency changes and increase the safety of the
`Function.toString` call.
**test plan:**
Manual testing again
**issue:**
https://github.com/facebook/react/issues/9589
* Use single entry point for SSR via browser field
* Add server.browser entry point and smoke tests
* Tweak bundle naming
* Fix import
* Re-record
* Fix the robot nits
* Add resetModules for some extra isolation
* Add react-dom-unstable-native-dependencies
react-native-web and react-primitives currently access a few internals
for shimming DOM events into native ones. Changes in react@16 packaging
hide these internals completely. This change adds a submodule to react-dom,
unstable-native-dependencies that includes the necessary modules to
continue enabling that method of dom-native event injection.
* Update ResponderEventPlugin to use "public" interfaces for test
In order to get some sort of smoke testing on
react-dom-unstable-native-dependencies, update ResponderEventPlugin-test
to use the "public" interfaces provided by react-dom and the new
react-dom/unstable-native dependencies
Also adds the missing references in package.json as well as missing
files required for unittests to do imports correctrly
Also exports injectComponentTree() which is required for the unittests
to re-set the shared component state between runs.
* Tweak bundle comment
* Bundle content updates from exporting injectComponentTree
* Added FB_DEV, FB_PROD to bundle types
* Run yarn prettier for -unstable-native-dependencies updates