Skip to content
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

Bug: MessageChannel in Scheduler prevents Jest test from exiting #26608

Open
victor-homyakov opened this issue Apr 12, 2023 · 11 comments
Open

Bug: MessageChannel in Scheduler prevents Jest test from exiting #26608

victor-homyakov opened this issue Apr 12, 2023 · 11 comments
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@victor-homyakov
Copy link
Contributor

React version: any
Scheduler version: any up to current (0.23.0)

Steps To Reproduce

  1. Create Jest unit test.
  2. Select JSDom as test environment so that runtime will not have setImmediate function.
  3. JSDom still does not implement MessageChannel MessageChannel is not defined jsdom/jsdom#2448. If MessageChannel is required to test some important functionality, one can add an implementation from Node.js as recommended in comment MessageChannel is not defined jsdom/jsdom#2448 (comment)
    window.MessageChannel = require('node:worker_threads').MessageChannel;
  4. Add Scheduler or React as a dependency and require it in the test or one of the files under test.
  5. Run test

Link to code example: https://github.com/victor-homyakov/scheduler-jest-jsdom-example

The current behavior

Test is endless. Jest won't stop. Console shows a message

Jest did not exit one second after the test run has completed.

'This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.

Running Jest with --detectOpenHandles outputs:

Jest has detected the following 1 open handle potentially keeping Jest from exiting:

  ●  MESSAGEPORT

    > 1 | require('scheduler');
        |                     ^

      at node_modules/scheduler/cjs/scheduler.development.js:569:17

The expected behavior

Code at

channel.port1.onmessage = performWorkUntilDeadline;
should unref the handle:

  channel.port1.onmessage = performWorkUntilDeadline;
  // Allow the thread to exit if this is the only active handle in the event system
  if (channel.port1.unref) {
    channel.port1.unref();
  }
@victor-homyakov victor-homyakov added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Apr 12, 2023
@victor-homyakov victor-homyakov changed the title Bug: MessageChannel in Scheduler has open handle and prevents Jest test from finishing Bug: MessageChannel in Scheduler prevents Jest test from finishing Apr 12, 2023
@victor-homyakov victor-homyakov changed the title Bug: MessageChannel in Scheduler prevents Jest test from finishing Bug: MessageChannel in Scheduler prevents Jest test from exiting Apr 12, 2023
@s100
Copy link

s100 commented Aug 24, 2023

I'm seeing the same issue during some experiments with Mocha testing. The suggested fix works for me. I will produce a minimal repro if that's considered desirable.

@victor-homyakov Are you aware of any kind of workaround for this?

@victor-homyakov
Copy link
Contributor Author

@victor-homyakov Are you aware of any kind of workaround for this?

The workaround is to use patched MessageChannel in JSDom, something like

const MessageChannelOriginal = require('node:worker_threads').MessageChannel;
class MessageChannel {
    constructor() {
        const channel = new MessageChannelOriginal();
        // Allow the thread to exit if this is the only active handle in the event system
        if (channel.port1.unref) {
            channel.port1.unref();
        }
        this.channel = channel;
    }
    get port1() {
        return this.channel.port1;
    }
    // ...
}
window.MessageChannel = MessageChannel;

@s100
Copy link

s100 commented Sep 25, 2023

Thank you very much for the workaround! In practice I found that simply unrefing the port immediately on creation did not do the trick, because as soon as scheduler calls channel.port1.onmessage = performWorkUntilDeadline the port becomes reffed again. I had to do something more complex:

const MessageChannelOriginal = global.MessageChannel
global.MessageChannel = class {
  constructor () {
    const channel = new MessageChannelOriginal()
    this.port1 = new Proxy(channel.port1, {
      set (port1, prop, value) {
        const result = Reflect.set(port1, prop, value)
        if (prop === 'onmessage') {
          port1.unref()
        }
        return result
      }
    })
    this.port2 = channel.port2
  }
}

Alternatively, as I happen to be using Mocha, I found that the --exit flag also worked.

Copy link

github-actions bot commented Apr 9, 2024

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Apr 9, 2024
@s100
Copy link

s100 commented Apr 12, 2024

Bump, this is still an issue for us.

@github-actions github-actions bot removed the Resolution: Stale Automatically closed due to inactivity label Apr 12, 2024
Copy link

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Jul 11, 2024
@victor-homyakov
Copy link
Contributor Author

Bump

@github-actions github-actions bot removed the Resolution: Stale Automatically closed due to inactivity label Jul 14, 2024
@victor-homyakov
Copy link
Contributor Author

Bump

Copy link

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Nov 21, 2024
@s100
Copy link

s100 commented Nov 21, 2024

Bump

@github-actions github-actions bot removed the Resolution: Stale Automatically closed due to inactivity label Nov 21, 2024
@petrloukota
Copy link

Bump

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants