inexorabletash/polyfill

0.1.33 - global undefined so assignment referring to .isNaN throws TypeError

Closed this issue · 6 comments

I'm getting the error Uncaught TypeError: Cannot read property 'isNaN' of undefined at

var $isNaN = global.isNaN;
(In Qt it's TypeError: 'undefined' is not an object (evaluating 'global.isNaN'))

If I break at

var undefined = (void 0); // Paranoia
, global is undefined.

I think this is carried into polyfill.js from

var $isNaN = global.isNaN;

Is this expected? I'm seeing this in Chrome and QtWeb 3.8.5 (I have a special project that depends on Qt).

global is passed in to the wrapping IIFE:

(function (global) {
  ...
}(this));

If you were loading this in an environment where this is not defined that would produce the error you're seeing. Are you possibly wrapping this in a script that leaves this undefined?

To add a bit more to this, I added some logging and found that the closure created at

(function (global) {
results in the global object reflecting the Window object. To me this says that even though both closures should execute in the same context (which should have global), that doesn't seem to be the case.

Thank you for the very fast reply.

To further research the scope, I added console log statements right before the closure (in the context IIFE would then execute) and found that at the first call (around like 495 of polyfill.js), global is undefined. Looking at where that closure ends (

}(self));
), I can see that it's called with self, not this even though it is this at
}(this));

I'm guessing that polyfill.js isn't up to date compared to es2016.js and at a glance, your tests don't cover polyfill.js because it's expected to contain only code tested from other files.

I tested this theory by manually updating rows 495-4268 of polyfill.js (in my local bower_components file) with the contents from the es2016.js file and tested again, but then I realized that my console.log just before that closer is showing "this" to be undefined so I'm continuing to investigate.

My full implementation is a "report-common.js" file which is created from grunt-contrib-concat and the first file in it is the polyfill.js file. That report-common.js file is loaded in with <script type="text/javascript" src="/scripts/report-common.js"></script> .

I'm continuing to debug starting with logging this right after each IIFE (I think that should be the exact context the IIFE will run);

I've found that a lot of your IIFE closures are called with self in polyfill.js, though not all (some use this), but in the top scope, I see no assignment of self and it doesn't exist except in the context of Window and this isn't window when that closure executes. Is that my environment then? Did you intend to use self there?

I've found that by adding self = self || window at the top of polyfill.js then replacing global.isNaN with self.isNaN, then I get past the isNaN error, but now I've git an error where .head is read-only and an assignment is being attempted at https://github.com/inexorabletash/polyfill/blob/master/polyfill.js#L4416
and is throwing Uncaught TypeError: Cannot assign to read only property 'head' of object '[object HTMLDocument]'

By disabling that line (just for testing), I get further still, but then hit TypeError: Cannot assign to read only property 'ELEMENT_NODE' of function 'function Node() { [native code] }' at https://github.com/inexorabletash/polyfill/blob/master/polyfill.js#L4643

It looks like there's clearly an assumption about the environment which isn't valid in my case if there isn't any issues you've found otherwise (like the fact that es2016.js code doesn't match what's in polyfill.js).

self is present in browsers. I avoided using it in the JS polyfills since those could plausibly be used outside a browser environment.

I've discovered that after running code through Babel (es2015 preset), things break so apparently Babel is messing with scope of IIFE's or global vars because I'm running into multiple instances where self, global and even this are undefined.

In case someone else hits this: I just found the issue and solution. I introduced Babel with the "es2015" preset in my project so I could use ES6 features, but release ES5 code. It turns out that the es2015 preset assumes the source code is ES6 (including use of modules) and I was feeding it source that wasn't intended to be used as modules SO, that code was getting wrapped in a way that destroyed scope (due to the inclusion of the commonJs babel plugin in the es2015 preset).

By using the "babel-preset-es2015-script" preset (must first npm install --save-dev babel-preset-es2015-script), this was avoided (until I move everything to a module system). This preset doesn't include the commonJs preset so it doesn't wrap the code for commonJs modules.

Here's where I found the answer: http://stackoverflow.com/a/34983495/2503764

Totally my fault, but hopefully this helps someone else :)