YuzuJS/setImmediate

postMessage is 'undefined' and throws 'setImmediate is not defined' error

Opened this issue · 7 comments

We are using setImmediate through a Promise polyfill (https://github.com/taylorhakes/promise-polyfill) and for the most part it is working perfectly. However, on a few sites, it is throwing a "setImmediate is not defined" error. I have traced the problem down to where it looks for postMessage (https://github.com/YuzuJS/setImmediate/blob/master/setImmediate.js#L87)

It is not getting through that if statement because postMessage is returning as undefined.

However, when I type postMessage in the console, it shows up as a function.

image

Is there a way that we can check to see if postMessage is available in the window object as well as in the global?

Am I missing something here?

We have two sites this is happening on and hundreds of sites where there is no issue (including all our dev sites).

I've done some additional digging and it looks like the conflict arises when another script sets self as a global. This force setImmediate to use that variable instead of the true global: https://github.com/YuzuJS/setImmediate/blob/master/setImmediate.js#L186

For example, one of the sites has this code:

function TradeShowROICalculator() {
	(selector = ".tradeshow-container"),
		(self = this),
		$(selector)
			.on("blur", "input", function() {
				readInputField(self, this);
			})
			.find("input")
			.each(function() {
				readInputField(self, this);
			});
}

So then when I output self before setImmediate runs, this is what I get:
image

Any thoughts on how to resolve this?

This is what it should look like:
image

It sounds like you nailed the origin of the problem by noticing that a global variable self was set by another library. Since setImmediate uses self on its last line of code, you can change it from this:

}(typeof self === "undefined" ? typeof global === "undefined" ? this : global : self));

To something like this:

}(typeof global === "undefined" ? typeof window === "undefined" ? this : window : global));
mbest commented

Any thoughts on how to resolve this?

Fix the broken code on the site. It should not be setting a global self.

@shuckster after further debugging I realized that webpack was directly adding in setImmediate (not the other polyfill). In order to fix this, I had to set setImmediate: false in my webpack config. I then manually added setImmediate and modified it by passing in window to get it to work. Works for now, but not ideal. Would love to use setImmediate right out of the box.

@mbest

Fix the broken code on the site. It should not be setting a global self.

Our code is running on clients sites, just like setImmediate is running in our code. We have no control over those global variables.

mbest commented

https://developer.mozilla.org/en-US/docs/Web/API/Window/self. No code should be setting the global self. Even so, setImmediate should probably prefer window to self.

Agreed. I have relayed to the site owners the need to fix that, but it's out of my hands at this point. I agree that setImmediate should prefer window though.