* Fix crash during server render.
setTimeout and clearTimeout may not be available in some server-render environments (such as ChakraCore in React.NET), and loading ReactScheduler.js will cause a crash unless the existence of the variables are checked via a typeof comparison.
https://github.com/reactjs/React.NET/issues/555
The crash did not occur in 16.4.0, and the change appears to have been introduced here: https://github.com/facebook/react/pull/12931/files#diff-bbebc3357e1fb99ab13ad796e04b69a6L47
I tested this by using yarn link and running it with a local copy of React.NET. I am unsure the best way to unit test this change, since assigning null to `setTimeout` causes an immediate crash within the Node REPL.
* Fix flow errors and log warning if setTimeout / clearTimeout are
not defined / not a function.
* Use invariant to assert setTimeout / clearTimeout are functions
* Remove use of invariant
* Explain
* Add fixture test for schedule running when tab is backgrounded
**what is the change?:**
Just adding a test to the fixture, where we can easily see whether
scheduled callbacks are called after switching away from the fixture
tab.
**why make this change?:**
We are about to fix the schedule module so that it still runs even when
the tab is in the backround.
**test plan:**
Manually tested the fixture, verified that it works as expected and
right now callbacks are not called when the tab is in the background.
**issue:**
Internal task T30754186
* Fall back to 'setTimeout' when 'requestAnimationFrame' is not called
**what is the change?:**
If 'requestAnimationFrame' is not called for 100ms we fall back to
'setTimeout' to schedule the postmessage.
**why make this change?:**
When you start loading a page, and then switch tabs,
'requestAnimationFrame' is throttled or not called until you come back
to that tab. That means React's rendering, any any other scheduled work,
are paused.
Users expect the page to continue loading, and rendering is part of the
page load in a React app. So we need to continue calling callbacks.
**test plan:**
Manually tested using the new fixture test, observed that the callbacks
were called while switched to another tab. They were called more
slowly, but that seems like a reasonable thing.
**issue:**
Internal task T30754186
* make arguments more explicit
* Fixes children when using dangerouslySetInnerHtml in a selected <option>
This fixes an inadvertent cast of undefined children to an empty string when creating an option tag that will be selected:
```
<select defaultValue="test">
<option value='test' dangerouslySetInnerHTML={{ __html: '‏ test'}} />
</select>
```
This causes an invariant error because both children and dangerouslySetInnerHTML are set.
* PR fix and new ReactDOMServerIntegrationForms test
* Account for null case
* Combine test cases into single test
* Add tests for failure cases
* Fix lint
* react-test-renderer injects itself into DevTools if present
* Fibers are always opted into ProfileMode if DevTools is present
* Added simple test for DevTools + always profiling behavior
* Do not add additional work to a batch that is already rendering.
Otherwise, the part of the tree that hasn't rendered yet will receive
the latest state, but the already rendered part will show the state
as it was before the intervening update.
* Reduce non-helpfulness of comments
Expiration times are computed by adding to the current time (the start
time). However, if two updates are scheduled within the same event, we
should treat their start times as simultaneous, even if the actual clock
time has advanced between the first and second call.
In other words, because expiration times determine how updates are
batched, we want all updates of like priority that occur within the same
event to receive the same expiration time. Otherwise we get tearing.
We keep track of two separate times: the current "renderer" time and the
current "scheduler" time. The renderer time can be updated whenever; it
only exists to minimize the calls performance.now.
But the scheduler time can only be updated if there's no pending work,
or if we know for certain that we're not in the middle of an event.
* Inline fbjs/lib/emptyObject
* Explicit naming
* Compare to undefined
* Another approach for detecting whether we can mutate
Each renderer would have its own local LegacyRefsObject function.
While in general we don't want `instanceof`, here it lets us do a simple check: did *we* create the refs object?
Then we can mutate it.
If the check didn't pass, either we're attaching ref for the first time (so we know to use the constructor),
or (unlikely) we're attaching a ref to a component owned by another renderer. In this case, to avoid "losing"
refs, we assign them onto the new object. Even in that case it shouldn't "hop" between renderers anymore.
* Clearer naming
* Add test case for strings refs across renderers
* Use a shared empty object for refs by reading it from React
* Remove string refs from ReactART test
It's not currently possible to resetModules() between several renderers
without also resetting the `React` module. However, that leads to losing
the referential identity of the empty ref object, and thus subsequent
checks in the renderers for whether it is pooled fail (and cause assignments
to a frozen object).
This has always been the case, but we used to work around it by shimming
fbjs/lib/emptyObject in tests and preserving its referential identity.
This won't work anymore because we've inlined it. And preserving referential
identity of React itself wouldn't be great because it could be confusing during
testing (although we might want to revisit this in the future by moving its
stateful parts into a separate package).
For now, I'm removing string ref usage from this test because only this is
the only place in our tests where we hit this problem, and it's only
related to string refs, and not just ref mechanism in general.
* Simplify the condition
In async mode, events are interleaved with rendering. If one of those
events mutates state that is later accessed during render, it can lead
to inconsistencies/tearing.
Restarting the render from the root is often sufficient to fix the
inconsistency. We'll flush the restart synchronously to prevent yet
another mutation from happening during an interleaved event.
We'll only restart during an async render. Sync renders are already
sync, so there's no benefit in restarting. (Unless a mutation happens
during the render phase, but we don't support that.)
* onFatal, onComplete, onSuspend, onYield
For every call to renderRoot, one of onFatal, onComplete, onSuspend,
and onYield is called upon exiting. We use these in lieu of returning a
tuple. I've also chosen not to inline them into renderRoot because these
will eventually be lifted into the renderer.
* Suspended high pri work forces lower priority work to expire early
If an error is thrown, and there is lower priority pending work, we
retry at the lower priority. The lower priority work should expire
at the same time at which the high priority work would have expired.
Effectively, this increases the priority of the low priority work.
Simple example: If an error is thrown during a synchronous render, and
there's an async update, the async update should flush synchronously in
case it's able to fix the error. I've added a unit test for
this scenario.
User provided timeouts should have the same behavior, but I'll leave
that for a future PR.
* Add isUsingKoreanIME function to check if a composition event was triggered by Korean IME
* Add Korean IME check alongside useFallbackCompositionData and disable fallback mode with Korean IME
We need a different "component tree" thingy for Fabric.
A lot of this doesn't really make much sense in a persistent world but
currently we can't dispatch events to memoizedProps on a Fiber since
they're pooled. Also, it's unclear what the semantics should be when we
dispatch an event that happened when the old props were in effect but now
we have new props already.
This implementation tries to use the last committed props but also fails
at that because we don't have a commit hook in the persistent mode.
However, at least it doesn't crash when dispatching. :)
* Remove rAF fork
**what is the change?:**
Undid https://github.com/facebook/react/pull/12837
**why make this change?:**
We originally forked rAF because we needed to pull in a particular
version of rAF internally at Facebook, to avoid grabbing the default
polyfilled version.
The longer term solution, until we can get rid of the global polyfill
behavior, is to initialize 'schedule' before the polyfilling happens.
Now that we have landed and synced
https://github.com/facebook/react/pull/12900 successfully, we can
initialize 'schedule' before the polyfill runs.
So we can remove the rAF fork. Here is how it will work:
1. Land this PR on Github.
2. Flarnie will quickly run a sync getting this change into www.
3. We delete the internal forked version of
'requestAnimationFrameForReact'.
4. We require 'schedule' in the polyfill file itself, before the
polyfilling happens.
**test plan:**
Flarnie will manually try the above steps locally and verify that things
work.
**issue:**
Internal task T29442940
* fix nits
* fix tests, fix changes from rebasing
* fix lint
* Remove enableSuspense flag from PendingPriority module
We're going to use this for suspending on error, too.
* Retry on error if there's lower priority pending work
If an error is thrown, and there's lower priority work, it's possible
the lower priority work will fix the error. Retry at the lower priority.
If an error is thrown and there's no more work to try, handle the error
like we normally do (trigger the nearest error boundary).
* Use native event dispatching instead of Simulate or SimulateNative
In #12629 @gaearon suggested that it would be better to drop usage of
`ReactTestUtils.Simulate` and `ReactTestUtils.SimulateNative`. In this
PR I’m attempting at removing it from a lot of places with only a few
leftovers.
Those leftovers can be categorized into three groups:
1. Anything that tests that `SimulateNative` throws. This is a property
that native event dispatching doesn’t have so I can’t convert that
easily. Affected test suites: `EventPluginHub-test`,
`ReactBrowserEventEmitter-test`.
2. Anything that tests `ReactTestUtils` directly. Affected test suites:
`ReactBrowserEventEmitter-test` (this file has one test that reads
"should have mouse enter simulated by test utils"),
`ReactTestUtils-test`.
3. Anything that dispatches a `change` event. The reason here goes a bit
deeper and is rooted in the way we shim onChange. Usually when using
native event dispatching, you would set the node’s `.value` and then
dispatch the event. However inside [`inputValueTracking.js`][] we
install a setter on the node’s `.value` that will ignore the next
`change` event (I found [this][near-perfect-oninput-shim] article
from Sophie that explains that this is to avoid onChange when
updating the value via JavaScript).
All remaining usages of `Simulate` or `SimulateNative` can be avoided
by mounting the containers inside the `document` and dispatching native
events.
Here some remarks:
1. I’m using `Element#click()` instead of `dispatchEvent`. In the jsdom
changelog I read that `click()` now properly sets the correct values
(you can also verify it does the same thing by looking at the
[source][jsdom-source]).
2. I had to update jsdom in order to get `TouchEvent` constructors
working (and while doing so also updated jest). There was one
unexpected surprise: `ReactScheduler-test` was relying on not having
`window.performance` available. I’ve recreated the previous
environment by deleting this property from the global object.
3. I was a bit confused that `ReactTestUtils.renderIntoDocument()` does
not render into the document 🤷
[`inputValueTracking.js`]: https://github.com/facebook/react/blob/392530104c00c25074ce38e1f7e1dd363018c7ce/packages/react-dom/src/client/inputValueTracking.js#L79
[near-perfect-oninput-shim]: https://sophiebits.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html
[jsdom-source]: https://github.com/jsdom/jsdom/blob/45b77f5d21cef74cad278d089937d8462c29acce/lib/jsdom/living/nodes/HTMLElement-impl.js#L43-L76
* Make sure contains are unlinked from the document even if the test fails
* Remove unnecessary findDOMNode calls
* Don’t error when returning an empty Fragment
When a fragment is reconciled, we directly move onto it’s children.
Since an empty `<React.Fragment/>` will have children of `undefined`,
this would always throw.
To fix this, we bail out in those cases.
* Test the update path as well
* Reuse existing code path
* An even more explicit solution that also fixes Flow
It looks like we accidentally removed a fallback condition for the
event target in IE9 when we dropped some support for IE8. This commit
adds the event target specific support code back to getEventTarget.js
Fixes#12506
* Fixed an issue with nested contexts unwinding when server rendering. GitHub issue #12984
* Fixed an issue with search direction and stricter false checking
* Use decrement infix operator
* Streamlined existence checks
* Streamlined assignment. Removed redundant comment. Use null for array values
* Made prettier
* Relaxed type checking and improved comment
* Improve test coverage
This commit removes a reference to inst._wrapperState, which was the
old way of tracking input state in the stack renderer.
This means we no longer need to pass the instance into the associated
function, allowing us to eliminate an exception for IE (and a TODO).
* Fix react-dom ReferenceError requestAnimationFrame in non-browser env (#13000)
The https://github.com/facebook/react/pull/12931 ( https://github.com/facebook/react/commit/79a740c6e32ca300d4e7ff55ab06de172d4237fd ) broke the server-side rendering: in the `fixtures/ssr` the following error appeared from the server-side when `localhost:3000` is requested:
```
ReferenceError: requestAnimationFrame is not defined
at /__CENSORED__/react/build/node_modules/react-dom/cjs/react-dom.development.js:5232:34
at Object.<anonymous> (/__CENSORED__/react/build/node_modules/react-dom/cjs/react-dom.development.js:17632:5)
at Module._compile (module.js:624:30)
at Module._extensions..js (module.js:635:10)
at Object.require.extensions.(anonymous function) [as .js] (/__CENSORED__/react/fixtures/ssr/node_modules/babel-register/lib/node.js:152:7)
at Module.load (module.js:545:32)
at tryModuleLoad (module.js:508:12)
at Function.Module._load (module.js:500:3)
at Module.require (module.js:568:17)
at require (internal/module.js:11:18)
```
The exception pointed to this line:
```js
// We capture a local reference to any global, in case it gets polyfilled after
// this module is initially evaluated.
// We want to be using a consistent implementation.
const localRequestAnimationFrame = requestAnimationFrame;
```
**Test plan**
1. In `react` repo root, `yarn && yarn build`.
2. In `fixtures/ssr`, `yarn && yarn start`,
3. In browser, go to `http://localhost:3000`.
4. Observe the fixture page, not the exception message.
* Move the requestAnimationFrameForReact check and warning to callsites (#13000)
According to the comment by @gaearon: https://github.com/facebook/react/pull/13001#issuecomment-395803076
* Use `invariant` instead of `throw new Error`, use the same message (#13000)
According to the comment by @gaearon: https://github.com/facebook/react/pull/13001#discussion_r194133355
* Set the correct initial value on input range
* Add description and update value diff check for input range
* add isHydrating argument and tests
* update node value according to isHydrating
* Initial failing unit test for error handling in schedule
**what is the change?:**
see title
**why make this change?:**
Adding tests for the error handling behavior we are about to add. This
test is failing, which gives us the chance to make it pass.
Wrote skeletons of some other tests to add.
Unit testing this way is really hacky, and I'm also adding to the
fixture to test this in the real browser environment.
**test plan:**
Ran new test, saw it fail!
* Add fixture for testing error handling in scheduler
**what is the change?:**
Added a fixture which does the following -
logs in the console to show what happens when you use
`requestAnimationFrame` to schedule a series of callbacks and some of
them throw errors.
Then does the same actions with the `scheduler` and verifies that it
behaves in a similar way.
Hard to really verify the errors get thrown at the proper time without
looking at the console.
**why make this change?:**
We want the most authentic, accurate test of how errors are handled in
the scheduler. That's what this fixture should be.
**test plan:**
Manually verified that this test does what I expect - right now it's
failing but follow up commits will fix that.
* Handle errors in scheduler
**what is the change?:**
We set a flag before calling any callback, and then use a 'try/finally'
block to wrap it. Note that we *do not* catch the error, if one is
thrown. But, we only unset the flag after the callback successfully
finishes.
If we reach the 'finally' block and the flag was not unset, then it
means an error was thrown.
In that case we start a new postMessage callback, to finish calling any
other pending callbacks if there is time.
**why make this change?:**
We need to make sure that an error thrown from one callback doesn't stop
other callbacks from firing, but we also don't want to catch or swallow
the error because we want engineers to still be able to log and debug
errors.
**test plan:**
New tests added are passing, and we verified that they fail without this
change.
* Add more tests for error handling in scheduler
**what is the change?:**
Added tests for more situations where error handling may come up.
**why make this change?:**
To get additional protection against this being broken in the future.
**test plan:**
Ran new tests and verified that they fail when error handling fails.
* callSafely -> callUnsafely
* Fix bugs with error handling in schedule
**what is the change?:**
- ensure that we properly remove the callback from the linked list, even
if it throws an error and is timed out.
- ensure that you can call 'cancelScheduledWork' more than once and it
is idempotent.
**why make this change?:**
To fix bugs :)
**test plan:**
Existing tests pass, and we'll add more tests in a follow up commit.
* Unit tests for error handling with timed out callbacks
**what is the change?:**
More unit tests, to cover behavior which we missed; error handling of
timed out callbacks.
**why make this change?:**
To protect the future!~
**test plan:**
Run the new tests.
* Adds fixture to test timed out callbacks with scheduler
**what is the change?:**
See title
In the other error handling fixture we compare 'scheduleWork' error
handling to 'requestAnimationFrame' and try to get as close as possible.
There is no 'timing out' feature with 'requestAnimationFrame' but
effectively the 'timing out' feature changes the order in which things
are called. So we just changed the order in the 'requestAnimationFrame'
version and that works well for illustrating the behavior we expect in
the 'scheduleWork' test.
**why make this change?:**
We need more test coverage of timed out callbacks.
**test plan:**
Executed the fixture manually in Firefox and Chrome. Results looked
good.
* fix rebase problems
* make fixture compensate for chrome JS speed
* ran prettier
* Remove 'cancelled' flag on callbackConfig in scheduler, add test
**what is the change?:**
- Instead of using a 'cancelled' flag on the callbackConfig, it's easier
to just check the state of the callbackConfig inside
'cancelScheduledWork' to determine if it's already been cancelled. That
way we don't have to remember to set the 'cancelled' flag every time we
call a callback or cancel it. One less thing to remember.
- We added a test for calling 'cancelScheduledWork' more than once,
which would have failed before.
Thanks @acdlite for suggesting this in code review. :)
**why make this change?:**
To increase stability of the schedule module, increase test coverage.
**test plan:**
Existing tests pass and we added a new test to cover this behavior.
* fix typo
* Fix for Flow issues in SimpleCacheProvider
**what is the change?:**
- Fixed some flow errors which were somehow swallowed when CI
originally
- Loosen flow types to avoid issue with recursive loop in Flow; https://github.com/facebook/flow/issues/5870
**why make this change?:**
To unbreak master and unblock other changes we want to make.
**test plan:**
Flow passes!
**issue:**
https://github.com/facebook/react/issues/12941
* Fix lints
* [simple-cache-provider] Use LRU cache eviction
Max size is hard-coded to 500. In the future, we should make this
configurable per resource.
* Evict PAGE_SIZE records from cache when max limit is reached