🏠 back to Observable

iife inside required library

#1

Hi,

I have a ascii animation library here which support UMD, here:

At some point within the factory I run an iief to capture browser quirks for passive event listeners like this:

(function(){
			var quirks = _LexiconMonoSeq.prototype.quirks,
				options = Object.defineProperty({},"passive",{
					get: function(){
						quirks.passiveSupported = true;
					}
				});
			$window.addEventListener("lexiconMonoSeqPassiveTest",null,options);
			quirks.disableScrollFunction = function(e){
				if(quirks.busy){return}
				$window.requestAnimationFrame(function(){
					quirks.busy = false;
				});
				quirks.busy = true;
				if(!e.cancelable) {
					return
				} else {
					e.preventDefault();
				}
			};
		})();

When I require my library:

LexiconMonoSeq = require("lexicon-mono-seq@1.1.2");

I get an error saying: LexiconMonoSeq = TypeError: Cannot read property ‘addEventListener’ of undefined

I cannot see the line of the error so I am guessing that some names are reserved such as window or document, so I went ahead and changed them to $window and $document respectively and published the current version. However I still get the error.

I see absolutely nothing on the developer console either. Can someone break down what is going on behind the scenes so I can get this up and working.

Thanks

#2

Hi Ibrahim!

Welcome to Observable! Sorry you’re running into some issues with this. For the debugging strategy, because this is happening in a required module and there’s an error happening in it, the best first approach is to toggle ‘Pause on uncaught exceptions’ on in the ‘Source’ tab of the Chrome Developer Tools,

image

Or in Firefox, the ‘Pause on exceptions’ checkbox under the Debugger tab

image

What this turns up is pretty much what you’ve already identified, but you’ll get a specific spot in the code where it occurs:

So next up is going up a level: $window is not defined, so where is this function being called with an undefined $window argument? We set a breakpoint right at the top in the UMD definition, and you’ll get

So out of the three options (AMD, CommonJS, and global), we can see that it’s taking the AMD path, the first one - because define is a function and has an amd property. And, in contrast to the other two paths, we aren’t explicitly passing root or root.document through. Per the AMD spec, it’ll call factory for you after loading any dependencies, and since in this case the dependencies array is [], it’s just going to call factory with no arguments.

So (I’m no AMD expert), but from my reading, AMD dependencies are really only other files and factor methods tend not to pass window & document in this way, so I posted a PR on the project that accesses window and document directly, and which works well for all the usage types. Here’s an example notebook that uses this tweaked version:

Hope that helps!

2 Likes
#3

Thank you so much for clarifying it Tom, I just merged the PR. It’s amazing how fast the response was, greatly appreciated, and learned a lot too!