-
Notifications
You must be signed in to change notification settings - Fork 47.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fiber ReactDOM shouldn't throw on import in Node environment if it's unused #9389
Conversation
5ace1a8
to
c751f2a
Compare
c751f2a
to
da44a1e
Compare
@gaearon Hi, PRs awaiting review. Please have a look. |
I don't think this is the right solution. The fact that DOM implementation might not have a way to schedule the animation seems like an implementation detail of the DOM renderer. So at the very least it shouldn't change anything in |
From your comment here
I'm a little confused: to lazy check for the rAF polyfill or to look at DOM implementation itself (which seems like a major overhaul). |
We can check |
1a459cc
to
ce00e20
Compare
|
||
// TODO: There's no way to cancel these, because Fiber doesn't atm. | ||
let rAF: (callback: (time: number) => void) => number; | ||
let rIC: (callback: (deadline: Deadline) => void) => number; | ||
|
||
if (!ExecutionEnvironment.canUseDOM) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gaearon /cc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a window.addEventListener
on L92 too. Use the same trick there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or fake polyfill requestIdleCallback
itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On L92 there a window.addEventListener
.
Fake polyfill requestIdleCallback
too?
|
||
// TODO: There's no way to cancel these, because Fiber doesn't atm. | ||
let rAF: (callback: (time: number) => void) => number; | ||
let rIC: (callback: (deadline: Deadline) => void) => number; | ||
|
||
if (!ExecutionEnvironment.canUseDOM) { | ||
global.requestAnimationFrame = function( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not put anything on global ourselves.
|
||
// TODO: There's no way to cancel these, because Fiber doesn't atm. | ||
let rAF: (callback: (time: number) => void) => number; | ||
let rIC: (callback: (deadline: Deadline) => void) => number; | ||
|
||
if (!ExecutionEnvironment.canUseDOM) { | ||
global.requestAnimationFrame = function( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take a look at the code below. We export rAF
and rIC
from this file. So we should just assign those variables instead of globals.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But that wont prevent the codepath accessing requestAnimationFrame
(and turns out requestIdleCallback
too. L101 is breaking on the server too.
So wrap the entire polyfilling code in else block of the if (!ExecutionEnvironment.canUseDOM) {
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I imagine something like
if (!ExecutionEnvironment.canUseDOM) {
} else if (typeof requestAnimationFrame !== 'function') {
} else if (typeof requestIdleCallback !== 'function') {
} else {
}
This way you won’t get into that condition at all if DOM is unavailable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the global assignment.
e99eb0a
to
fc0972d
Compare
@gaearon Requested changes have been made. |
Can we also add a test for this? "Can import findDOMNode in Node environment." The test would have a try-finally block in which it deletes global.requestAnimationFrame() and global.requestIdleCallback(), calls jest.resetModules(), and then tries to require('ReactDOM'). In the finally block it would restore the deleted globals. |
I'm not entirely familiar with the testing stack yet. This led to the following:
Also, I added to 2 identical tests. One with the try/finally block as you suggested. Other, using |
No, you don’t need to do this. I think you should move them to
That sounds fine.
I’d like to keep deletions like this confined to a single test case. So let’s use the |
describe('ReactDOMFrameScheduling (try/finally)', () => { | ||
it('can import findDOMNode in Node environment.', () => { | ||
var ReactDOM, ReactDOMFeatureFlags, ExecutionEnvironment; | ||
var _requestAnimationFrame = global.requestAnimationFrame; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming nitpick: let's call this previousRAF
(and previousRIC
).
Also let's add tests both for:
|
16d8d3a
to
d9eaa9a
Compare
|
global.requestAnimationFrame = undefined; | ||
global.requestIdleCallback = undefined; | ||
jest.resetModules(); | ||
require('ReactDOM'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually expected to throw since it determines you're in DOM mode. You need to keep this test (but change it to assert that it throws), and add another test that fools canUseDOM
somehow to return false
(look for existing tests that might do something similar—maybe it's enough to delete window.document
or something like that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about disableNewFiberFeatures
tests that are failing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe they’re failing because they don’t expect a new resetModules
in an arbitrary test? Perhaps it’s better to keep these two tests in a different file then, but keep them wrapped in the useFiber
check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Back next to ReactDOMFrameScheduling
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea.
d9eaa9a
to
fe4187d
Compare
bbcc27d
to
aaf2d1a
Compare
@gaearon Tests have been added.
|
@gaearon ^^ |
Let's write const describeFiber = ReactDOMFeatureFlags.useFiber ? describe : xdescribe;
describeFiber('ReactDOMFrameScheduling', () => {
// ...
}); This way it would get skipped in Stack completely. I think this should work (
You probably want to do something like git fetch orign
git rebase origin/master |
93ed2b6
to
abf5cc2
Compare
I guess you meant upstream. It still didn't work. When I ran prettier again locally, it prettifying the files all over again Also, I had to write a dummy |
You don't need to have an |
Updating.. |
And the prettier issue? |
Did you run |
I've been using the npm commands as mentioned in the Contributing docs. Running yarn now.. |
I haven't had this issue before |
Since you last checked the source out, Prettier has updated. You are running an older version of Prettier so this is why it formats differently. Running |
I vaguely remember running npm install after seeing the prettier update commit. Turns out I hadn't. Thank you so much. |
33f3ebc
to
a6ca10a
Compare
@gaearon All good? Squash the two commits into one? |
jest.resetModules(); | ||
expect(() => { | ||
require('ReactDOM'); | ||
}).toThrow(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you test for specific error message here please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. My bad actually. I have pushed the changes. Please have a look.
a6ca10a
to
0729812
Compare
0729812
to
63ccd6f
Compare
This looks good, thank you! I’m not sure the Node behavior fully makes sense here (maybe we should throw inside of these methods) but at least I’m glad to get those tests in, and we can iterate on this further. cc @sebmarkbage if he has concerns. |
Patch for #9102