makeplane / makeplane/plane

Safari incompatibility: gantt-layout-loader uses unguarded window.requestIdleCallback

Open
#8,988 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
59.6k
Forks
5.8k
Avg merge
1d 22h
Merged PRs (30d)
49

Description

Describe the bug

Navigating to a project's Work Items page in Safari renders the React error boundary ("Looks like something went wrong") instead of the work items.

The root cause is a TypeError from gantt-layout-loader-*.js:

TypeError: window.requestIdleCallback is not a function.
(In 'window.requestIdleCallback(()=>{h.current&&(S.current=`${h.current.offsetHeight}px`)})',
 'window.requestIdleCallback' is undefined)
  at gantt-layout-loader-Bameferh.js:1:5524

Safari does not ship requestIdleCallback (still unimplemented as of Safari 17). The call site does not feature-detect.

React errors #418 and #423 follow, but those are cascade from the initial throw.

To reproduce

  1. Self-hosted Plane CE v1.3.0
  2. Open Safari on macOS or iOS, log in
  3. Open any project, click Work items
  4. Error boundary renders instead of the kanban or list

Backend is fine. A HAR capture shows all 366 requests returning 200, including /api/.../issues/... with valid grouped JSON.

Expected behavior

Work items render in Safari like they do in Chrome and Firefox.

Suggested fix

Feature-detect the API or ship a polyfill in the entry bundle.

Minimal feature-detect:

const ric = window.requestIdleCallback || ((cb) => setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 50 }), 1));

The Gantt code path appears to use requestIdleCallback for non-critical layout measurement, so a setTimeout fallback should be visually acceptable. Polyfill packages like requestidlecallback-polyfill are well under 1 kB.

Workaround for self-hosters

Inject the polyfill via a reverse-proxy sub_filter on </head>. Tested on Plane 1.3.0 + Safari 17.x with nginx in front of plane-web:

location / {
    proxy_pass http://web;
    proxy_set_header Accept-Encoding "";
    sub_filter_once on;
    sub_filter '</head>' '<script>if(!window.requestIdleCallback){window.requestIdleCallback=function(c){return setTimeout(function(){c({didTimeout:false,timeRemaining:function(){return 50}})},1)};window.cancelIdleCallback=function(i){clearTimeout(i)}}</script></head>';
}

Environment

  • Plane CE 1.3.0, self-hosted (Docker)
  • Safari 17.x on macOS: broken
  • Firefox 129+ on macOS: works
  • Chrome 130+ on macOS: works

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the failure on the Work Items page in Safari and inspect the gantt-layout-loader-*.js path mentioned in the report to locate the unguarded requestIdleCallback call. Add a feature-detected fallback or polyfill for the non-critical layout measurement, then verify that Work items render in Safari and that Chrome and Firefox remain unaffected.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend, web-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.