fix(web): add Safari fallback for requestIdleCallback#9137
fix(web): add Safari fallback for requestIdleCallback#9137KanteshMurade wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughThe PR installs a requestIdleCallback/cancelIdleCallback polyfill at app bootstrap to prevent Safari compatibility crashes. idle-task.ts exports requestIdle/cancelIdle wrappers with setTimeout fallbacks; polyfills/index.ts invokes the installer at module load; entry.client.tsx imports polyfills before React hydration. ChangesSafari requestIdleCallback Polyfill Setup
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/core/lib/idle-task.ts`:
- Around line 11-37: The fallback implementations and availability checks should
use globalThis instead of window to avoid runtime errors when window is
undefined: update requestIdleFallback and cancelIdleFallback to call
globalThis.setTimeout and globalThis.clearTimeout, and change the runtime checks
in requestIdle and cancelIdle to use typeof globalThis !== "undefined" and
typeof globalThis.requestIdleCallback / globalThis.cancelIdleCallback ===
"function" so you only call globalThis.requestIdleCallback(globalCallback,
options) when available and otherwise return requestIdleFallback(callback) /
cancelIdleFallback(id).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2707e4a8-912b-4ba0-864a-2c084b23bf1d
📒 Files selected for processing (3)
apps/web/app/entry.client.tsxapps/web/core/lib/idle-task.tsapps/web/core/lib/polyfills/index.ts
| const requestIdleFallback = (callback: IdleRequestCallback): number => { | ||
| const start = Date.now(); | ||
|
|
||
| return window.setTimeout(() => { | ||
| callback({ | ||
| didTimeout: false, | ||
| timeRemaining: () => Math.max(0, 50 - (Date.now() - start)), | ||
| }); | ||
| }, 1); | ||
| }; | ||
|
|
||
| const cancelIdleFallback = (id: number) => { | ||
| window.clearTimeout(id); | ||
| }; | ||
|
|
||
| export const requestIdle = (callback: IdleRequestCallback, options?: IdleRequestOptions): number => { | ||
| if (typeof window !== "undefined" && typeof window.requestIdleCallback === "function") | ||
| return window.requestIdleCallback(callback, options); | ||
|
|
||
| return requestIdleFallback(callback); | ||
| }; | ||
|
|
||
| export const cancelIdle = (id: number) => { | ||
| if (typeof window !== "undefined" && typeof window.cancelIdleCallback === "function") | ||
| return window.cancelIdleCallback(id); | ||
|
|
||
| return cancelIdleFallback(id); |
There was a problem hiding this comment.
Use globalThis timers in fallbacks to prevent no-window runtime crashes.
The fallback path is selected when window is unavailable, but both fallbacks still dereference window, which can throw immediately in that environment.
Suggested fix
-const requestIdleFallback = (callback: IdleRequestCallback): number => {
+const requestIdleFallback = (
+ callback: IdleRequestCallback,
+ options?: IdleRequestOptions
+): number => {
const start = Date.now();
- return window.setTimeout(() => {
+ return globalThis.setTimeout(() => {
callback({
didTimeout: false,
timeRemaining: () => Math.max(0, 50 - (Date.now() - start)),
});
- }, 1);
+ }, options?.timeout ?? 1);
};
const cancelIdleFallback = (id: number) => {
- window.clearTimeout(id);
+ globalThis.clearTimeout(id);
};
export const requestIdle = (callback: IdleRequestCallback, options?: IdleRequestOptions): number => {
if (typeof window !== "undefined" && typeof window.requestIdleCallback === "function")
return window.requestIdleCallback(callback, options);
- return requestIdleFallback(callback);
+ return requestIdleFallback(callback, options);
};🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/core/lib/idle-task.ts` around lines 11 - 37, The fallback
implementations and availability checks should use globalThis instead of window
to avoid runtime errors when window is undefined: update requestIdleFallback and
cancelIdleFallback to call globalThis.setTimeout and globalThis.clearTimeout,
and change the runtime checks in requestIdle and cancelIdle to use typeof
globalThis !== "undefined" and typeof globalThis.requestIdleCallback /
globalThis.cancelIdleCallback === "function" so you only call
globalThis.requestIdleCallback(globalCallback, options) when available and
otherwise return requestIdleFallback(callback) / cancelIdleFallback(id).
Description
Fixes a Safari/iOS crash caused by unguarded usage of
window.requestIdleCallbackin the project layout/gantt view.Safari does not currently support
requestIdleCallbackby default, which caused the following runtime error:TypeError: window.requestIdleCallback is not a functionThis PR adds a shared compatibility fallback for:
requestIdleCallbackcancelIdleCallbackThe polyfill is installed during client startup before React hydration, while preserving native behavior in Chrome and Firefox.
Type of Change
Screenshots and Media (if applicable)
N/A
Test Scenarios
requestIdleCallbackis unavailableReferences
Closes #9134
Summary by CodeRabbit