From 6c6f66e3455e424288548149487431dfadd9afea Mon Sep 17 00:00:00 2001 From: dsc Date: Thu, 9 Dec 2010 14:08:10 -0800 Subject: [PATCH] Patches accessor functions into future for the browsers I'm supporting. --- src/future.js | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 130 insertions(+), 14 deletions(-) diff --git a/src/future.js b/src/future.js index 5531d95..f30db9d 100644 --- a/src/future.js +++ b/src/future.js @@ -1,15 +1,23 @@ (function(_Object, _Array, _Function){ -var P = "prototype" -, AP = _Array[P] -, FP = _Function[P] -, slice = AP.slice -, objToString = _Object[P].toString +var P = "prototype" +, FP = _Function[P] + +, AP = _Array[P] +, _slice = AP.slice + +, OP = _Object[P] +, hasOwn = OP.hasOwnProperty +, getget = OP.__lookupGetter__ +, getset = OP.__lookupSetter__ +, setget = OP.__defineGetter__ +, setset = OP.__defineSetter__ +, objToString = OP.toString ; if ( !_Array.slice ) { _Array.slice = function slice(a){ - return slice.apply(a, slice.call(arguments, 1)); + return _slice.apply(a, _slice.call(arguments, 1)); }; } @@ -80,30 +88,138 @@ if ( !AP.reduce ) { } } - +if ( !_Array.isArray ) { + _Array.isArray = function isArray(o) { return objToString.call(o) === '[object Array]'; }; +} // JavaScript 1.8.5 if ( !FP.bind ) { FP.bind = function bind( context ){ var fn = this, - args = slice.call(arguments, 1); + args = _slice.call(arguments,1); return function(){ - return fn.apply(context, args.concat( slice.call(arguments,0) )); + return fn.apply(context, args.concat( _slice.call(arguments,0) )); }; }; } if ( !_Object.getPrototypeOf ) { - _Object.getPrototypeOf = + _Object['getPrototypeOf'] = ( (typeof "".__proto__ === "object") - ? function(object){ return object.__proto__; } - : function(object){ return object.constructor[P]; } + ? function getPrototypeOf(o){ return o.__proto__; } + : function getPrototypeOf(o){ return o.constructor[P]; } ); } -if ( !_Array.isArray ) { - _Array.isArray = function isArray(o) { return objToString.call(o) === '[object Array]'; }; +if ( !_Object.keys ) { + _Object['keys'] = + function keys(o){ + var k, keys = []; + for ( k in o ) + if (hasOwn.call(o,k)) keys.push(k); + return keys; + }; +} + +if ( !_Object.defineProperty ) { + + function isFunction(f){ + return typeof f === "function"; + } + + function cleanDescriptor(desc){ + if (typeof desc !== "object" || desc === null) + throw new TypeError("Property description must be an object: "+desc); + + var d = {} + , get = desc.get, set = desc.set + , hasValue = hasOwn.call(desc, 'value') + ; + + if (hasOwn.call(desc, 'get') && get !== undefined) { + if (!isFunction(get)) + throw new TypeError("Getter must be a function: "+get); + d.get = get; + } + + if (hasOwn.call(desc, 'set') && set !== undefined) { + if (!isFunction(set)) + throw new TypeError("Setter must be a function: "+set); + d.set = set; + } + + if ( hasValue && (d.get || d.set) ) + throw new TypeError("Invalid property. A property cannot both have accessors and be writable or have a value: "+desc); + + if ( hasValue ) + d.value = desc.value; + + return d; + } + + _Object['defineProperty'] = + function defineProperty(o, prop, desc){ + if (typeof o !== "object" || o === null) + throw new TypeError("Object.defineProperty called on non-object: "+o); + + desc = cleanDescriptor(desc); + if ( 'value' in desc ) { + delete o[prop]; + o[prop] = desc.value; + } else { + if ( desc.get ) setget.call(o, prop, desc.get); + if ( desc.set ) setset.call(o, prop, desc.set); + } + + return o; + }; + + _Object['defineProperties'] = + function defineProperties(o, props) { + if (typeof o !== "object" || o === null) + throw new TypeError("Object.defineProperty called on non-object: "+o); + + props = Object(props); + var k, descs = {}; + + // Perform all the error checks before mutating anything + for (k in props) + if (hasOwn.call(props,k)) descs[k] = cleanDescriptor(props[k]); + + // Now we can start changing things + for (k in descs) + _Object.defineProperty(o, k, descs[k]); + + return o; + } + + _Object['getOwnPropertyDescriptor'] = + function getOwnPropertyDescriptor(o, prop){ + if (typeof o !== "object" || o === null) + throw new TypeError("Object.getOwnPropertyDescriptor called on non-object: "+o); + + if ( !hasOwn.call(o,prop) ) + return undefined; + + var getter = getget.call(o, prop) + , setter = getset.call(o, prop) + , desc = { 'configurable':true, 'enumerable':true }; + + // Data Descriptor + if (getter === undefined && setter === undefined) { + desc['value'] = o[prop]; + desc['writable'] = true; + + // Accessor Descriptor + } else { + if (getter) desc['get'] = getter; + if (setter) desc['set'] = setter; + } + + return desc; + }; } + })(Object, Array, Function); -- 1.7.0.4