fix-ie

Ironically-named bundle of useful polyfills for Internet Explorer 8-9

Usage no npm install needed!

<script type="module">
  import fixIe from 'https://cdn.skypack.dev/fix-ie';
</script>

README

Fix-IE

Ironically-named bundle of polyfills for Internet Explorer 8-9.

Contents:

  • HTML5 Shiv 3.7.3
  • Hack to get Object.defineProperty working on native JS objects.
  • EventTarget methods:
    • addEventListener
    • removeEventListener
  • Element-related properties:
    • el.classList (Also available here)
    • el.childElementCount
    • el.firstElementChild
    • el.lastElementChild
    • el.nextElementSibling
    • el.previousElementSibling
  • Node-related properties:
    • node.textContent
  • Window-related properties/methods:
    • window.getComputedStyle
    • window.innerWidth
    • window.innerHeight
    • window.pageXOffset
    • window.pageYOffset
  • Various ES5/ES6 language extensions:
    • ES5 Array extensions (every, filter, forEach, indexOf, lastIndexOf, map, reduce, reduceRight, some)
    • Array.isArray
    • ChildNode.remove
    • Number.isNaN
    • Date.now
    • String.prototype.trim
    • String.prototype.repeat
    • Object.defineProperties

Credits:

IE8PP

IE8PP stands for "IE8 Property Punch". It's a twisted hack used to get Object.defineProperty working on native JavaScript objects in IE8, which otherwise only supports using defineProperty on DOM elements. Pass it a constructor function, and use the returned value to overwrite the original:

    function Point(x, y){
        this.x = x;
        this.y = y;
        
        Object.defineProperty(this, "coords", {
            get: function(){
                return [this.x, this.y];
            }
        });
    }
    
    if(window.IE8PP)
        Point = IE8PP(Point);
    
    var test = new Point(13, 16);
    console.log(test.coords); // [13, 16]

"How the f-..."

This works because it's returning an HTML element, detached from the document tree. The original constructor function is fired within the context of the detached HTML node, causing all references to this to point to a shadow element. All properties/methods of the function's prototype are assigned to the HTML instance too.

Obviously you wouldn't expect this to work without limitations, and you'd be right:

  • Forget about instanceof: Everything your function would return is now technically an instance of an <s> element.
  • Subclassing? Not on this boat. __proto__ is nonsense according to IE8. Therefore, so are your hopes of having it understand prototypal inheritance.

This sounds a lot shakier than it actually is. As long as your class function defines instance properties from the constructor, and you aren't reliant on prototype chains, you won't have to touch a line of code to cater to IE8. Well, other than the obvious IE8PP call. Remember to run it before creating any instances, as well as assigning "static" methods:

    function Point(){
        /* Stuff, etc */
    }
    
    if(window.IE8PP)
        Point = IE8PP(Point);
    
    Point.fromArray = function(arr){ return new Point(arr[0], arr[1]); }
    Point.zero = Point.fromArray([0, 0]);

Yeah this hack is freakin' stupid, but so is Internet Explorer. Dumb problems often lead to dumb solutions.