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

MessageChannel is not defined #2448

Open
TheJoshuaEvans opened this issue Dec 5, 2018 · 8 comments
Open

MessageChannel is not defined #2448

TheJoshuaEvans opened this issue Dec 5, 2018 · 8 comments

Comments

@TheJoshuaEvans
Copy link

Basic info:

I am attempting to use Zombie.js (which uses jsdom) to debug Message Channel generation, but it doesn't seem to be defined. According to the MDN docs, the MessageChannel constructor has support going all the way back to IE10, so it seems strange that it's not supported here

  • Node.js version: 10.10.0
  • jsdom version: 13.0.0

Minimal reproduction case

'use strict';

// Let's see if MessageChannel is supported
let html = `
<!DOCTYPE html>
<body>
  <h1 id='title'>
    Does MessageChannel Exist?
  </h1>
  <script>
    var title = document.getElementById('title');
    try {
      window.channel = new MessageChannel();
    } catch(e) {
      console.log('Error caught: ' + e.message)
    }

    if (window.channel) {
    	title.innerHTML = 'MessageChannel Exists!';
    } else {
    	title.innerHTML = 'MessageChannel Does not Exist :(';
    }
  </script>
</body>
</html>
`;

const { JSDOM } = require('jsdom');
const { window } = new JSDOM(html, {runScripts: 'dangerously'});

console.log(window.eval('document.getElementById("title").innerHTML'));
// Expected -> 'MessageChannel Exists!'
// Actual ---> 'MessageChannel Does not Exist :('

Running the above node file should print the string "MessageChannel Exists!" and produce no errors. However, when running using jsdom a "MesssageChannel is not defined" error is thrown, and the console logs "MessageChannel Does not Exist :("

How does similar code behave in browsers?

Example of working code in JSFiddle:
https://jsfiddle.net/hvLpg6tm/5/

The HTML provided is exactly the same

@GeniaT
Copy link

GeniaT commented Mar 25, 2019

Same error, MessageChannel is not defined. Context: I use Jest and run a createWriteStream method from "streamsaver". Does a workaround exist maybe? Thanks

@TheJoshuaEvans
Copy link
Author

Unfortunately I did not find a workaround in this library :(

That doesn't mean there isn't one, however...

@bbruneau
Copy link

@TheJoshuaEvans Did you find one elsewhere?

@TheJoshuaEvans
Copy link
Author

Been a while since I touched this. When I was working on this I wound up just switching to puppeteer and eating the performance cost

@brettz9
Copy link

brettz9 commented Sep 29, 2019

Looks like one could just do this as of Node 10.5.0:

window.MessageChannel = require('worker_threads').MessageChannel;

Source: https://nodejs.org/api/worker_threads.html#worker_threads_class_messagechannel

However, one needs to pass Node the --experimental-worker flag.

@gaearon
Copy link

gaearon commented Mar 18, 2021

If someone adds this, there is one concern that I think needs to be resolved.

jsdom sandboxes timers. I.e. setTimeout and setInterval don't hold the Node process hostage if you call window.close(). They're automatically cancelled.

I believe that jsdom should do the same for MessageChannel ports, if it were to add window.MessageChannel. Concretely, window.close() should also close all open ports. Otherwise, the Node process won't exit.

@dominikj111
Copy link

I just encountered this issue during my testing, but not sure if we need something else than this:

window.MessageChannel = jest.fn().mockImplementation(() => {
	return {
		port1: {
			postMessage: jest.fn(),
		},
		port2: {
			addEventListener: jest.fn(),
			removeEventListener: jest.fn(),
		},
	};
});

As I don't need to test sending messages in my tests, it works for me. Do you really need text messaging?

@tianjunnew
Copy link

window.MessageChannel = jest.fn().mockImplementation(() => {
  let onmessage;
  return {
    port1: {
      set onmessage(cb) {
        onmessage = cb;
      },
    },
    port2: {
      postMessage: data => {
        onmessage?.({ data });
      },
    },
  };
});

works for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants