-
Notifications
You must be signed in to change notification settings - Fork 47k
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
Fix crash during server render in react 16.4.1. #13088
Conversation
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. reactjs/React.NET#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.
Is there any way you can shim it on your side? We could take this but then it's highly likely we'll break it again. It's also plausible we'll start relying on e.g. Promise so if your environment is very unusual then you'll keep running into those issues. |
Thanks for the fast response. I'll investigate adding a shim on React.NET for those functions and expect that it will break again in the future. Would you be open to accepting the patch anyway so we stop getting crashes in the meantime? I opened a PR directly since this one took a similar approach: #13000 I'll look at fixing the flow errors, do you have any suggestions on what to do? Should we return a function that warns instead? cc @Daniel15 |
@gaearon - Relying on
ReactJS.NET uses a pretty standard V8 or ChakraCore environment for server-side rendering. |
not defined / not a function.
@dustinsoftware In the meantime we can patch the version of React bundled with ReactJS.NET (although that means it'll still be broken for people that load their own version of React rather than using the bundled one). Either that or just shim |
We generally target Node environment with the server renderer. Node also has I don’t think the server side renderer uses the scheduler. You’re likely seeing this issue because some component imports regular |
const localSetTimeout = | ||
typeof setTimeout === 'function' | ||
? setTimeout | ||
: warning( |
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 looks a bit misleading, as if we’re using its return value.
Let’s just keep undefined there explicitly and then warn later.
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.
These are relatively hot paths and I'd like to avoid checking for something that for all intents and purposes will be true in the supported environments. (SSR doesn't currently call these functions.)
Let's remove the invariants? If Flow wants them, feel free to use any
, e.g.
const localSetTimeout = typeof setTimeout !== 'undefined' ? setTimeout : (undefined: any);
@@ -104,6 +94,11 @@ if (!canUseDOM) { | |||
callback: FrameCallbackType, | |||
options?: {timeout: number}, | |||
): CallbackIdType { | |||
invariant( | |||
typeof localSetTimeout === 'function', | |||
'localSetTimeout is not a function. Please load a polyfill that defines this 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.
localSetTimeout
is a variable name so it doesn't mean anything to somebody reading this. That said, I don't think we want an invariant at all.
Ah, yes I did add that because of flow. I’ll push a fix.
…On Thu, Jun 21, 2018 at 16:58, Dan Abramov ***@***.***> wrote:
***@***.**** requested changes on this pull request.
These are relatively hot paths and I'd like to avoid checking for
something that for all intents and purposes will be true in the supported
environments. (SSR doesn't currently call these functions.)
Let's remove the invariants? If Flow wants them, feel free to use any,
e.g.
const localSetTimeout = typeof setTimeout !== 'undefined' ? setTimeout : (undefined: any);
------------------------------
In packages/react-scheduler/src/ReactScheduler.js
<#13088 (comment)>:
> @@ -104,6 +94,11 @@ if (!canUseDOM) {
callback: FrameCallbackType,
options?: {timeout: number},
): CallbackIdType {
+ invariant(
+ typeof localSetTimeout === 'function',
+ 'localSetTimeout is not a function. Please load a polyfill that defines this function.',
localSetTimeout is a variable name so it doesn't mean anything to
somebody reading this. That said, I don't think we want an invariant at all.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#13088 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA5hFuNBYwCxwupPa8to_KdpJF_awBcYks5t_DMVgaJpZM4UyoQq>
.
|
I may be misunderstanding but it sounds like you prefer to have error
message at all, so that’s what I pushed. If I misunderstood I can restore
the warning inside an ”if dev mode” block so it is optimized out in
production mode.
On Thu, Jun 21, 2018 at 20:35, Dustin Masters <dustin@dustinsoftware.com>
wrote:
… Ah, yes I did add that because of flow. I’ll push a fix.
On Thu, Jun 21, 2018 at 16:58, Dan Abramov ***@***.***>
wrote:
> ***@***.**** requested changes on this pull request.
>
> These are relatively hot paths and I'd like to avoid checking for
> something that for all intents and purposes will be true in the supported
> environments. (SSR doesn't currently call these functions.)
>
> Let's remove the invariants? If Flow wants them, feel free to use any,
> e.g.
>
> const localSetTimeout = typeof setTimeout !== 'undefined' ? setTimeout : (undefined: any);
>
> ------------------------------
>
> In packages/react-scheduler/src/ReactScheduler.js
> <#13088 (comment)>:
>
> > @@ -104,6 +94,11 @@ if (!canUseDOM) {
> callback: FrameCallbackType,
> options?: {timeout: number},
> ): CallbackIdType {
> + invariant(
> + typeof localSetTimeout === 'function',
> + 'localSetTimeout is not a function. Please load a polyfill that defines this function.',
>
> localSetTimeout is a variable name so it doesn't mean anything to
> somebody reading this. That said, I don't think we want an invariant at all.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <#13088 (review)>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AA5hFuNBYwCxwupPa8to_KdpJF_awBcYks5t_DMVgaJpZM4UyoQq>
> .
>
|
ReactDOM: size: 🔺+0.1%, gzip: 🔺+0.1% Details of bundled changes.Comparing: 5b3d17a...96881ff react-dom
react-art
react-scheduler
Generated by 🚫 dangerJS |
This fixes a crash that only occurs in react-dom 16.4.1.
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.
reactjs/React.NET#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.