Code Monkey home page Code Monkey logo

es5-shim's Introduction

es5-shim Version Badge

github actions coverage dependency status dev dependency status License Downloads

npm badge

es5-shim.js and es5-shim.min.js monkey-patch a JavaScript context to contain all EcmaScript 5 methods that can be faithfully emulated with a legacy JavaScript engine. Note: As es5-shim.js is designed to patch the native Javascript engine, it should be the library that is loaded first.

es5-sham.js and es5-sham.min.js monkey-patch other ES5 methods as closely as possible. For these methods, as closely as possible to ES5 is not very close. Many of these shams are intended only to allow code to be written to ES5 without causing run-time errors in older engines. In many cases, this means that these shams cause many ES5 methods to silently fail. Decide carefully whether this is what you want. Note: es5-sham.js requires es5-shim.js to be able to work properly.

Tests

The tests are written with the Jasmine BDD test framework. To run the tests, navigate to /tests/ , or, simply npm install and npm test.

Shims

Complete tests

Shams

  • ⚠️ Object.create

    For the case of simply "begetting" an object that inherits prototypically from another, this should work fine across legacy engines.

    ⚠️ The second argument is passed to Object.defineProperties which will probably fail either silently or with extreme prejudice.

  • ⚠️ Object.getPrototypeOf

    This will return "undefined" in some cases. It uses __proto__ if it's available. Failing that, it uses constructor.prototype, which depends on the constructor property of the object's prototype having not been replaced. If your object was created like this, it won't work:

      function Foo() {
      }
      Foo.prototype = {};
    

    Because the prototype reassignment destroys the constructor property.

    This will work for all objects that were created using Object.create implemented with this library.

  • ⚠️ Object.getOwnPropertyNames

    This method uses Object.keys, so it will not be accurate on legacy engines.

  • Object.isSealed

    Returns "false" in all legacy engines for all objects, which is conveniently guaranteed to be accurate.

  • Object.isFrozen

    Returns "false" in all legacy engines for all objects, which is conveniently guaranteed to be accurate.

  • Object.isExtensible

    Works like a charm, by trying very hard to extend the object then redacting the extension.

May fail

  • ⚠️ Object.getOwnPropertyDescriptor

    The behavior of this shim does not conform to ES5. It should probably not be used at this time, until its behavior has been reviewed and been confirmed to be useful in legacy engines.

  • ⚠️ Object.defineProperty

    In the worst of circumstances, IE 8 provides a version of this method that only works on DOM objects. This sham will not be installed. The given version of defineProperty will throw an exception if used on non-DOM objects.

    In slightly better circumstances, this method will silently fail to set "writable", "enumerable", and "configurable" properties.

    Providing a getter or setter with "get" or "set" on a descriptor will silently fail on engines that lack "defineGetter" and "defineSetter", which include all versions of IE.

    https://github.com/es-shims/es5-shim/issues#issue/5

  • ⚠️ Object.defineProperties

    This uses the Object.defineProperty shim.

  • Object.seal

    Silently fails on all legacy engines. This should be fine unless you are depending on the safety and security provisions of this method, which you cannot possibly obtain in legacy engines.

  • Object.freeze

    Silently fails on all legacy engines. This should be fine unless you are depending on the safety and security provisions of this method, which you cannot possibly obtain in legacy engines.

  • Object.preventExtensions

    Silently fails on all legacy engines. This should be fine unless you are depending on the safety and security provisions of this method, which you cannot possibly obtain in legacy engines.

Example of applying ES compatibility shims in a browser project

<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.14/es5-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.14/es5-sham.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.5/es6-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.5/es6-sham.min.js"></script>
<script src="other-libs.js"></script>

es5-shim's People

Contributors

bbqsrc avatar bryanforbes avatar cscott avatar domenic avatar eriklynd avatar fbuecklers avatar fidian avatar fizker avatar fschaefer avatar gerardpaapu avatar gozala avatar hazzik avatar iwyg avatar jdalton avatar kennethkufluk avatar kossnocorp avatar kriskowal avatar ljharb avatar michaelficarra avatar petermichaux avatar raynos avatar re1ro avatar robotlolita avatar rwaldron avatar samsonjs avatar termi avatar webreflection avatar xavierm02 avatar xotic750 avatar yaffle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

es5-shim's Issues

IS0 8601 parsing bug

console.log(new Date(Date.parse("2011-06-15T21:40:05+06:00")));

Chrome native: Wed Jun 15 2011 21:40:05 GMT+0600 (YEKST) // right
Chrome with attached es5-shim script: Thu Jun 16 2011 09:40:05 GMT+0600 (YEKST) // wrong

Date.parse unit test fails in Saf5.1.1

expect(Date.parse('+033658-09-27T01:46:40.000Z')).toBe(1e15);

Line 16

fails in Safari 5.1.1 in windows 7.

It returns 999999913600000 instead of 1e15.

(Apologies, I added this unit test and should have caught it earlier!)

suggestion for Function#bind

if (typeof target.apply != "function" || typeof target.call != "function")
            return new TypeError();

should change to:

if (typeof target.apply != "function" || typeof target.call != "function")
            throw new TypeError();

and I wonder why not just simplify to:

// If IsCallable(func) is false, throw a TypeError exception.
    if (typeof target !== 'function') {
      throw new TypeError('Bind must be called on a function');
    }

Another suggestion is:

if (result !== null && Object(result) === result) {
  return result;
}

can be reduced to:

if (Obect(result) === result) {
  return result;
}

because Object(null) !== null

My forked version:
https://github.com/seajs/dew/blob/master/src/es5-safe/es5-safe.js#L45

Best regards!

IE8 issues, Date#parse issue after uglifying

It seems like nobody tried to run tests in IE8, there are a lot of not passed tests.

Primary I spent a lot of time to figure out Date issue in IE8 after uglifying the code.

Browser reported issue here, .parse method couldn't be accessed:

https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js#L945

I figured out that removing the function name here solves the problem.

https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js#L940

so:
var Date = function(Y, M, D, h, m, s, ms) {

Best,
Oleg

[[HasInstance]] internal method wrong result after using Function.prototype.bind

var Point = function (x, y) {
    this.x = x;
    this.y = y;
};

var ZeroPoint = Point.bind( null, 0, 0 );

var zeroPoint = new ZeroPoint();

zeroPoint instanceof ZeroPoint; // must be true, but return false with current 'bind' shim
zeroPoint instanceof Point    ; // true

Problem: zeroPoint not instance of ZeroPoint class

Original comment here(RUS)

My personal solution is:

Function.prototype.bind = function (object, var_args) {
    //If IsCallable(Target) is false, throw a TypeError exception.
    if (typeof this != "function") {
        throw new TypeError("Function.prototype.bind called on incompatible " + this);
    }
    var __method = this, args = Array.prototype.slice.call(arguments, 1),
        _result = function () {
            return __method.apply(
                this instanceof _result ?
                    this ://The `object` value is ignored if the bound function is constructed using the new operator.
                    object,
                args.concat(Array.prototype.slice.call(arguments)));
    };
    if(__method.prototype) {
        _result.prototype = Object.create(__method.prototype);
    }
    return _result;
};

es5-shim would be:

if (!Function.prototype.bind) {
    Function.prototype.bind = function bind(that) {
        var target = this;
        if (typeof target != "function") {
            throw new TypeError("Function.prototype.bind called on incompatible " + target);
        }

        var args = slice.call(arguments, 1);

        var bound = function () {

            if (this instanceof bound) {

                //delete lines, rename self to this
                //var F = function(){};
                //F.prototype = target.prototype;
                //var self = new F;

                var result = target.apply(
                    this,
                    args.concat(slice.call(arguments))
                );
                if (Object(result) === result) {
                    return result;
                }
                return this;

            } else {

                return target.apply(
                    that,
                    args.concat(slice.call(arguments))
                );

            }

        };

        //add
        if(target.prototype)
            bound.prototype = Object.create(target.prototype);

        return bound;
    };
}

What do you think about it?

Clarify copyright/license statement

The copyright message at the top of the es5-shim file is short and neat, which is great, but doesn't match the information provided in the LICENSE file.

LICENSE:

Copyright 2009, 2010 Kristopher Michael Kowal. All rights reserved.

es5-shim.js:

/*!
    Copyright (c) 2009, 280 North Inc. http://280north.com/
    MIT License. http://github.com/280north/narwhal/blob/master/README.md
*/

Additionally, the minified code has no copyright/license included at all. Is this the way it should be distributed?

partially support non-enumerability

https://gist.github.com/1672142

Since we emulate defineProperty and Object.keys we can keep a record of any non-enumerable properties defined through our defineProperty shim and then reference them in Object.keys.

This means that non-enumerable works for Object.keys but fails with for..in

Is this of value or do we just not want to support non-enumerability?

Regression in Date.parse

Commit c8b5f18 introduced the following regression in browsers without native ISO date parsing support:

isNaN(Date.parse("2011-08-16T12:16:33Z")) === true

Before that commit, such strings successfully passed through Date.parse.

I tried writing unit tests for this, but I could not get it to fail in modern browsers in the same style as has been done for Array and Function, because we rely on the native implementation of Date.parse in implementing our own version, so if the native implementation successfully parses the string, the tests will always pass.

Essentially the problem is that the new isoDateExpression introduced in that commit does not match the above string.

question: why `self.length >>> 0`?

I've seen a lot of people using length >>> 0 on their code (including the MDN shims) but never really understood why, just want to clarify the reasoning behing it, I know what >>> does just don't understand why it's being used in this case..

if length is negative it will return Math.pow(2, 32) + length (that's what zero-fill right shift does with negative numbers..) if length is NaN it will return 0 and if value is positive it will do a Math.floor() (because bitwise operations works with integers..)

why not simply do ~~length?? it will take care of NaN and Math.floor() and negative lengths will be ignored since loops won't execute..

~~ 0.35;  // 0
~~ 9.75;  // 9
~~ -9.75; // -9
~~ '';    // 0
~~ 'foo'; // 0
~~ NaN;   // 0

in the current setup if self.length is negative (probably won't happen :P) it will cause an "infinite" loop.

IE8 defineProperty/getOwnPropertyDescriptor clash with shim

As currently implemented, the Object.defineProperty shim will not install on IE8 because IE8 already has such a method. However, the built-in IE8 method only works when applied to DOM objects.

Because the shim does not get installed, the emulation of value: property descriptors on arbitrary objects is not available although it could be. (get: and set: descriptors are a lost cause). The shim installation needs better detection of IE8 (see http://blogs.msdn.com/b/ie/archive/2010/09/07/transitioning-existing-code-to-the-es5-getter-setter-apis.aspx) and should probably and the installed shim should first call the built-in method and then only call the the emulation if the built-in throws).

IE8 also has a DOM only getOwnPropertyDescriptor so the same issues apply to it.

Two sets of unit tests

You seem to have two sets of unit tests. This is rather confusing.

If I wanted to add more tests which should I expand upon?

Can we deprecate one of them?

es5-shim limitation need to be explicitly stated

A concern:

Since this package is getting a fair amount of twitter and blog visibility, I'm concerned that some false expectations are being created. In particular, it isn't clear from the description of the project that it while it provides an ES5 compatible API but that it does not and cannot provide ES5 semantic extensions that are not already present in the "older" browser.

This shows up in all legacy browsers for functions such as Object.freeze and the inability to set property attributes. For IE<9 browsers it will show up as an inability to define getter/setter properties. User's of this package really should be warned of these limitations.

IE8 function Date{}

It seems that the minifier makes code with bad varible names. On IE the the references to the function name fail.

Date=function(a){var c=function g(b,c,d,f,h,i,j){var k=arguments.length

should be

Date=function(a){var g=function(b,c,d,f,h,i,j){var k=arguments.length

or perhaps

change the source to

 // Date.length === 7
 function Date(Y, M, D, h, m, s, ms) {

I would expect a nested function declaration to be the best solution

Many tests broken in ie8

Using real ie8 (i.e. not ie9's "act as ie8" mode), 57 of the 156 tests are currently failing for me in ie8. Many of these issues are not mentioned under the "dubious shims" section in the README (e.g. tests for filter, indexOf fail).

Using ie9's emulate ie8 mode, I get 3 failures, all for Object.isExtensible.

Date.parse test fails in IE8 (Expected NaN to be 28800000)

The issue is the overloaded Date object does not provide any of the Date behaviors and returns NaN Number(new Date(1970, 0)) line 787. A fix is to use the NativeDate to construct this value.

But, I'm wondering why we replace the entire interface of Date. Why not just replace the parse method? That way the native impls will/should still work, like .toString() and .valueOf(). UPDATED: it looks like the native methods are exposed via "newDate.prototype.constructor = Date".

I will provide a pull request for the above mentioned fix.

Correct bad Date.prototype.toJSON polyfills from elsewhere

Douglas Crockford's json2.js, for example, defines a Date.prototype.toJSON function that does not pad extended years with zeros as the es5-shim does in Date.prototype.toISOString does.

es5-shim can redefine a bad Date.prototype.toJSON by changing

if (!Date.prototype.toJSON) {

to

if (!Date.prototype.toJSON ||
    (new Date(-62198755200000).toJSON().indexOf('-000001') === -1)) {

This also means people using json2.js need to include json2.js in their environment before including es5-shim as defining Date.prototype.toJSON means other things will not be defined in json2.js

improper toISOString() output

Date.prototype.toISOString outputs unpadded values, like '1970-1-1T22:30:00Z'.

A fix is below, from MDN:

if (!Date.prototype.toISOString) {
    function pad(n) {
      return n < 10 ? '0' + n : n;
    }
    Date.prototype.toISOString = function toISOString() {
        return (
            this.getUTCFullYear() + "-" +
            pad(this.getUTCMonth() + 1) + "-" +
            pad(this.getUTCDate()) + "T" +
            pad(this.getUTCHours()) + ":" +
            pad(this.getUTCMinutes()) + ":" +
            pad(this.getUTCSeconds()) + "Z"
        );
    }
}

Tested fine in IE7, but could use some performance tweaks.

Date#toJSON

new Date().toJSON not calls Date.prototype.toISOString in Opera 11.6x/12 (seems, it always uses native "toISOString")

new Date(NaN).toJSON() should return null according to spec (throws error in Opera 11.6/12, Safari 5.1.5 with both native and es5-shim version)

fix is here:
#110

Remove partially shimmed support.

Shims that cover only part of the primary function of an ES5 method are potentially dangerous because they provide a false sense of support.

Devs checking with truthy inferences may assume for example that if (Object.create) { ... } it is fully functional Object.create(null). We should remove all shims that cover only part of a methods functionality.

Date#toISOString/Native Date object bugs

Safari 5.1.5

console.log(new Date(-1).toISOString()); // Safari 5.1.5 "1969-12-31T23:59:59.-01Z" - es5-shim not applyied, because of
// "if (!Date.prototype.toISOString || (new Date(-62198755200000).toISOString().indexOf('-000001') === -1)) {"

// console.log(new Date(-1).toISOString()); should be "1969-12-31T23:59:59.999Z"

Opera 11.61, Opera 12
(new Date(-3509827334573292)).getUTCMonth() === 12 // - 13 monthes in a year !

console.log(new Date(-3509827334573292).toISOString());
// Opera 11.61/Opera 12 (with es5-shim): -109253-13-01T10:37:06.708Z
// should be -109252-01-01T10:37:06.708Z

despriptor typo

Hi!

Please, consider fixing despriptor typo at lines 389, 393

TIA,
--Vladimir

error in [].indexOf

['1', '2'].indexOf('1') // returns -1, but should return 0 (testet in IE8)

The bug is here:

if (arguments.length > 0)
i = toInteger(arguments[1]);

I'm pretty sure you want to test, wether arguments.length is greater than 1. But in this case ['1', '2'].indexOf('1', undefined) would also return -1 although all browsers with native support do still return 0.

In which browsers do you test, before you tag a new release?

indexOf not safe?

I just wonder: Did you just forget to mention indexOf in the list of safe shims or is there a reason why it is not safe to use? I guess when lastIndexOf is safe then there couldn't be a reason why indexOf couldn't be implemented in a safe way.

Add tests

I think QUnit will be good choice.

Add project to the dojo foundation?

A number of people have suggested this idea to me, so I figure I'd bring it up here.

es5-shim is the leader of the pack in many regards. There are a number of other efforts that try to do the same thing:

But es5-shim seemingly has the most careful implementation and best tests. Also the most community and expert review.

It would be great to help solidify its status as the defacto es5 shim. Putting it under the guise of the Dojo Foundation would help do that, I think.

Do others think this is a worthwhile idea?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.