| // Copyright 2009-2012 by contributors, MIT License |
| // vim: ts=4 sts=4 sw=4 expandtab |
| |
| // Module systems magic dance |
| (function (definition) { |
| // RequireJS |
| if (typeof define == "function") { |
| define(definition); |
| // YUI3 |
| } else if (typeof YUI == "function") { |
| YUI.add("es5-sham", definition); |
| // CommonJS and <script> |
| } else { |
| definition(); |
| } |
| })(function () { |
| |
| // ES5 15.2.3.2 |
| // http://es5.github.com/#x15.2.3.2 |
| if (!Object.getPrototypeOf) { |
| // https://github.com/kriskowal/es5-shim/issues#issue/2 |
| // http://ejohn.org/blog/objectgetprototypeof/ |
| // recommended by fschaefer on github |
| Object.getPrototypeOf = function getPrototypeOf(object) { |
| return object.__proto__ || ( |
| object.constructor |
| ? object.constructor.prototype |
| : prototypeOfObject |
| ); |
| }; |
| } |
| |
| // ES5 15.2.3.3 |
| // http://es5.github.com/#x15.2.3.3 |
| if (!Object.getOwnPropertyDescriptor) { |
| var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a non-object: "; |
| |
| Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { |
| if ((typeof object != "object" && typeof object != "function") || object === null) { |
| throw new TypeError(ERR_NON_OBJECT + object); |
| } |
| // If object does not owns property return undefined immediately. |
| if (!owns(object, property)) { |
| return; |
| } |
| |
| // If object has a property then it's for sure both `enumerable` and |
| // `configurable`. |
| var descriptor = { enumerable: true, configurable: true }; |
| |
| // If JS engine supports accessor properties then property may be a |
| // getter or setter. |
| if (supportsAccessors) { |
| // Unfortunately `__lookupGetter__` will return a getter even |
| // if object has own non getter property along with a same named |
| // inherited getter. To avoid misbehavior we temporary remove |
| // `__proto__` so that `__lookupGetter__` will return getter only |
| // if it's owned by an object. |
| var prototype = object.__proto__; |
| object.__proto__ = prototypeOfObject; |
| |
| var getter = lookupGetter(object, property); |
| var setter = lookupSetter(object, property); |
| |
| // Once we have getter and setter we can put values back. |
| object.__proto__ = prototype; |
| |
| if (getter || setter) { |
| if (getter) { |
| descriptor.get = getter; |
| } |
| if (setter) { |
| descriptor.set = setter; |
| } |
| // If it was accessor property we're done and return here |
| // in order to avoid adding `value` to the descriptor. |
| return descriptor; |
| } |
| } |
| |
| // If we got this far we know that object has an own property that is |
| // not an accessor so we set it as a value and return descriptor. |
| descriptor.value = object[property]; |
| return descriptor; |
| }; |
| } |
| |
| // ES5 15.2.3.4 |
| // http://es5.github.com/#x15.2.3.4 |
| if (!Object.getOwnPropertyNames) { |
| Object.getOwnPropertyNames = function getOwnPropertyNames(object) { |
| return Object.keys(object); |
| }; |
| } |
| |
| // ES5 15.2.3.5 |
| // http://es5.github.com/#x15.2.3.5 |
| if (!Object.create) { |
| Object.create = function create(prototype, properties) { |
| var object; |
| if (prototype === null) { |
| object = { "__proto__": null }; |
| } else { |
| if (typeof prototype != "object") { |
| throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); |
| } |
| var Type = function () {}; |
| Type.prototype = prototype; |
| object = new Type(); |
| // IE has no built-in implementation of `Object.getPrototypeOf` |
| // neither `__proto__`, but this manually setting `__proto__` will |
| // guarantee that `Object.getPrototypeOf` will work as expected with |
| // objects created using `Object.create` |
| object.__proto__ = prototype; |
| } |
| if (properties !== void 0) { |
| Object.defineProperties(object, properties); |
| } |
| return object; |
| }; |
| } |
| |
| // ES5 15.2.3.6 |
| // http://es5.github.com/#x15.2.3.6 |
| |
| // Patch for WebKit and IE8 standard mode |
| // Designed by hax <hax.github.com> |
| // related issue: https://github.com/kriskowal/es5-shim/issues#issue/5 |
| // IE8 Reference: |
| // http://msdn.microsoft.com/en-us/library/dd282900.aspx |
| // http://msdn.microsoft.com/en-us/library/dd229916.aspx |
| // WebKit Bugs: |
| // https://bugs.webkit.org/show_bug.cgi?id=36423 |
| |
| function doesDefinePropertyWork(object) { |
| try { |
| Object.defineProperty(object, "sentinel", {}); |
| return "sentinel" in object; |
| } catch (exception) { |
| // returns falsy |
| } |
| } |
| |
| // check whether defineProperty works if it's given. Otherwise, |
| // shim partially. |
| if (Object.defineProperty) { |
| var definePropertyWorksOnObject = doesDefinePropertyWork({}); |
| var definePropertyWorksOnDom = typeof document == "undefined" || |
| doesDefinePropertyWork(document.createElement("div")); |
| if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { |
| var definePropertyFallback = Object.defineProperty; |
| } |
| } |
| |
| if (!Object.defineProperty || definePropertyFallback) { |
| var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; |
| var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " |
| var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + |
| "on this javascript engine"; |
| |
| Object.defineProperty = function defineProperty(object, property, descriptor) { |
| if ((typeof object != "object" && typeof object != "function") || object === null) { |
| throw new TypeError(ERR_NON_OBJECT_TARGET + object); |
| } |
| if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) { |
| throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); |
| } |
| // make a valiant attempt to use the real defineProperty |
| // for I8's DOM elements. |
| if (definePropertyFallback) { |
| try { |
| return definePropertyFallback.call(Object, object, property, descriptor); |
| } catch (exception) { |
| // try the shim if the real one doesn't work |
| } |
| } |
| |
| // If it's a data property. |
| if (owns(descriptor, "value")) { |
| // fail silently if "writable", "enumerable", or "configurable" |
| // are requested but not supported |
| /* |
| // alternate approach: |
| if ( // can't implement these features; allow false but not true |
| !(owns(descriptor, "writable") ? descriptor.writable : true) || |
| !(owns(descriptor, "enumerable") ? descriptor.enumerable : true) || |
| !(owns(descriptor, "configurable") ? descriptor.configurable : true) |
| ) |
| throw new RangeError( |
| "This implementation of Object.defineProperty does not " + |
| "support configurable, enumerable, or writable." |
| ); |
| */ |
| |
| if (supportsAccessors && (lookupGetter(object, property) || |
| lookupSetter(object, property))) |
| { |
| // As accessors are supported only on engines implementing |
| // `__proto__` we can safely override `__proto__` while defining |
| // a property to make sure that we don't hit an inherited |
| // accessor. |
| var prototype = object.__proto__; |
| object.__proto__ = prototypeOfObject; |
| // Deleting a property anyway since getter / setter may be |
| // defined on object itself. |
| delete object[property]; |
| object[property] = descriptor.value; |
| // Setting original `__proto__` back now. |
| object.__proto__ = prototype; |
| } else { |
| object[property] = descriptor.value; |
| } |
| } else { |
| if (!supportsAccessors) { |
| throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); |
| } |
| // If we got that far then getters and setters can be defined !! |
| if (owns(descriptor, "get")) { |
| defineGetter(object, property, descriptor.get); |
| } |
| if (owns(descriptor, "set")) { |
| defineSetter(object, property, descriptor.set); |
| } |
| } |
| return object; |
| }; |
| } |
| |
| // ES5 15.2.3.7 |
| // http://es5.github.com/#x15.2.3.7 |
| if (!Object.defineProperties) { |
| Object.defineProperties = function defineProperties(object, properties) { |
| for (var property in properties) { |
| if (owns(properties, property) && property != "__proto__") { |
| Object.defineProperty(object, property, properties[property]); |
| } |
| } |
| return object; |
| }; |
| } |
| |
| // ES5 15.2.3.8 |
| // http://es5.github.com/#x15.2.3.8 |
| if (!Object.seal) { |
| Object.seal = function seal(object) { |
| // this is misleading and breaks feature-detection, but |
| // allows "securable" code to "gracefully" degrade to working |
| // but insecure code. |
| return object; |
| }; |
| } |
| |
| // ES5 15.2.3.9 |
| // http://es5.github.com/#x15.2.3.9 |
| if (!Object.freeze) { |
| Object.freeze = function freeze(object) { |
| // this is misleading and breaks feature-detection, but |
| // allows "securable" code to "gracefully" degrade to working |
| // but insecure code. |
| return object; |
| }; |
| } |
| |
| // detect a Rhino bug and patch it |
| try { |
| Object.freeze(function () {}); |
| } catch (exception) { |
| Object.freeze = (function freeze(freezeObject) { |
| return function freeze(object) { |
| if (typeof object == "function") { |
| return object; |
| } else { |
| return freezeObject(object); |
| } |
| }; |
| })(Object.freeze); |
| } |
| |
| // ES5 15.2.3.10 |
| // http://es5.github.com/#x15.2.3.10 |
| if (!Object.preventExtensions) { |
| Object.preventExtensions = function preventExtensions(object) { |
| // this is misleading and breaks feature-detection, but |
| // allows "securable" code to "gracefully" degrade to working |
| // but insecure code. |
| return object; |
| }; |
| } |
| |
| // ES5 15.2.3.11 |
| // http://es5.github.com/#x15.2.3.11 |
| if (!Object.isSealed) { |
| Object.isSealed = function isSealed(object) { |
| return false; |
| }; |
| } |
| |
| // ES5 15.2.3.12 |
| // http://es5.github.com/#x15.2.3.12 |
| if (!Object.isFrozen) { |
| Object.isFrozen = function isFrozen(object) { |
| return false; |
| }; |
| } |
| |
| // ES5 15.2.3.13 |
| // http://es5.github.com/#x15.2.3.13 |
| if (!Object.isExtensible) { |
| Object.isExtensible = function isExtensible(object) { |
| // 1. If Type(O) is not Object throw a TypeError exception. |
| if (Object(object) !== object) { |
| throw new TypeError(); // TODO message |
| } |
| // 2. Return the Boolean value of the [[Extensible]] internal property of O. |
| var name = ''; |
| while (owns(object, name)) { |
| name += '?'; |
| } |
| object[name] = true; |
| var returnValue = owns(object, name); |
| delete object[name]; |
| return returnValue; |
| }; |
| } |
| |
| }); |