Refactor Polyfill.js, use Object.defineProperty if available

This commit is contained in:
rolux 2013-12-04 09:47:35 +01:00
parent 828e814812
commit 4471a8657f

View file

@ -1,9 +1,18 @@
'use strict'; 'use strict';
Ox.polyfill = {}; (function(window) {
var canDefineProperty = !!Object.defineProperty && (function() {
try {
Object.defineProperty({}, 'a', {});
return true;
} catch (e) {} // IE 8
}()),
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
log;
Ox.polyfill = {};
(function() {
var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
/*@ /*@
Ox.polyfill.atob <f> see https://developer.mozilla.org/en/DOM/window.atob Ox.polyfill.atob <f> see https://developer.mozilla.org/en/DOM/window.atob
> Ox.polyfill.atob('Cg==') > Ox.polyfill.atob('Cg==')
@ -14,7 +23,7 @@ Ox.polyfill = {};
Ox.polyfill.atob = function(string) { Ox.polyfill.atob = function(string) {
var binary = '', ret = ''; var binary = '', ret = '';
String(string).replace(/=/g, '').split('').forEach(function(char) { String(string).replace(/=/g, '').split('').forEach(function(char) {
binary += Ox.pad(digits.indexOf(char).toString(2), 'left', 6, '0'); binary += Ox.pad(chars.indexOf(char).toString(2), 'left', 6, '0');
}); });
while (binary.length >= 8) { while (binary.length >= 8) {
ret += Ox.char(parseInt(binary.slice(0, 8), 2)); ret += Ox.char(parseInt(binary.slice(0, 8), 2));
@ -36,14 +45,12 @@ Ox.polyfill = {};
}); });
binary = Ox.pad(binary, Math.ceil(binary.length / 6) * 6, '0') binary = Ox.pad(binary, Math.ceil(binary.length / 6) * 6, '0')
while (binary) { while (binary) {
ret += digits[parseInt(binary.slice(0, 6), 2)]; ret += chars[parseInt(binary.slice(0, 6), 2)];
binary = binary.slice(6); binary = binary.slice(6);
} }
return Ox.pad(ret, Math.ceil(ret.length / 4) * 4, '='); return Ox.pad(ret, Math.ceil(ret.length / 4) * 4, '=');
}; };
}());
(function(window) {
/*@ /*@
Ox.polyfill.bind <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind Ox.polyfill.bind <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
<script> <script>
@ -80,16 +87,15 @@ Ox.polyfill = {};
ret.prototype = new fn(); ret.prototype = new fn();
return ret; return ret;
}; };
})(this);
/*@ /*@
Ox.polyfill.every <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every Ox.polyfill.every <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
> Ox.polyfill.every.call([0, 1, 2], function(v, i) { return v == i; }) > Ox.polyfill.every.call([0, 1, 2], function(v, i) { return v == i; })
true true
> Ox.polyfill.every.call([true, true, false], Ox.identity) > Ox.polyfill.every.call([true, true, false], Ox.identity)
false false
@*/ @*/
Ox.polyfill.every = function(iterator, that) { Ox.polyfill.every = function(iterator, that) {
if (this === void 0 || this === null || typeof iterator !== 'function') { if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError(); throw new TypeError();
} }
@ -101,14 +107,14 @@ Ox.polyfill.every = function(iterator, that) {
} }
} }
return ret; return ret;
}; };
/*@ /*@
Ox.polyfill.filter <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter Ox.polyfill.filter <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
> Ox.polyfill.filter.call([2, 1, 0], function(v, i) { return v == i; }) > Ox.polyfill.filter.call([2, 1, 0], function(v, i) { return v == i; })
[1] [1]
@*/ @*/
Ox.polyfill.filter = function(iterator, that) { Ox.polyfill.filter = function(iterator, that) {
if (this === void 0 || this === null || typeof iterator !== 'function') { if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError(); throw new TypeError();
} }
@ -120,18 +126,18 @@ Ox.polyfill.filter = function(iterator, that) {
} }
} }
return ret; return ret;
}; };
/*@ /*@
Ox.polyfill.forEach <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach Ox.polyfill.forEach <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach
<script> <script>
Ox.test.array = []; Ox.test.array = [];
Ox.polyfill.forEach.call([1, 2, 3], function(v, i) { Ox.test.array.push([v, i])}) Ox.polyfill.forEach.call([1, 2, 3], function(v, i) { Ox.test.array.push([v, i])})
</script> </script>
> Ox.test.array > Ox.test.array
[[1, 0], [2, 1], [3, 2]] [[1, 0], [2, 1], [3, 2]]
@*/ @*/
Ox.polyfill.forEach = function(iterator, that) { Ox.polyfill.forEach = function(iterator, that) {
if (this === void 0 || this === null || typeof iterator !== 'function') { if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError(); throw new TypeError();
} }
@ -141,16 +147,16 @@ Ox.polyfill.forEach = function(iterator, that) {
iterator.call(that, array[i], i, array); iterator.call(that, array[i], i, array);
} }
} }
}; };
/*@ /*@
Ox.polyfill.indexOf <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf Ox.polyfill.indexOf <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
> Ox.polyfill.indexOf.call([1, 2, 3, 2, 1], 2) > Ox.polyfill.indexOf.call([1, 2, 3, 2, 1], 2)
1 1
> Ox.polyfill.indexOf.call([1, 2, 3, 2, 1], 4) > Ox.polyfill.indexOf.call([1, 2, 3, 2, 1], 4)
-1 -1
@*/ @*/
Ox.polyfill.indexOf = function(value) { Ox.polyfill.indexOf = function(value) {
if (this === void 0 || this === null) { if (this === void 0 || this === null) {
throw new TypeError(); throw new TypeError();
} }
@ -162,31 +168,31 @@ Ox.polyfill.indexOf = function(value) {
} }
} }
return ret; return ret;
}; };
/*@ /*@
Ox.polyfill.isArray <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray Ox.polyfill.isArray <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
> Ox.polyfill.isArray([]) > Ox.polyfill.isArray([])
true true
> Ox.polyfill.isArray((function() { return arguments; }())) > Ox.polyfill.isArray((function() { return arguments; }()))
false false
> Ox.polyfill.isArray({0: 0, length: 1}) > Ox.polyfill.isArray({0: 0, length: 1})
false false
@*/ @*/
Ox.polyfill.isArray = function(value) { Ox.polyfill.isArray = function(value) {
return Object.prototype.toString.call(value) == '[object Array]'; return Object.prototype.toString.call(value) == '[object Array]';
}; };
/*@ /*@
Ox.polyfill.JSON <o> see https://github.com/douglascrockford/JSON-js Ox.polyfill.JSON <o> see https://github.com/douglascrockford/JSON-js
> Ox.polyfill.JSON.parse('{"a": [1, 2], "b": [3, 4]}') > Ox.polyfill.JSON.parse('{"a": [1, 2], "b": [3, 4]}')
{a: [1, 2], b: [3, 4]} {a: [1, 2], b: [3, 4]}
> Ox.polyfill.JSON.stringify([(function(){ return arguments; }()), false, null, 0, -0, Infinity, NaN, / /, void 0]) > Ox.polyfill.JSON.stringify([(function(){ return arguments; }()), false, null, 0, -0, Infinity, NaN, / /, void 0])
'[{},false,null,0,0,null,null,{},null]' '[{},false,null,0,0,null,null,{},null]'
> Ox.polyfill.JSON.stringify(new Date()).length > Ox.polyfill.JSON.stringify(new Date()).length
24 24
@*/ @*/
Ox.polyfill.JSON = (function() { Ox.polyfill.JSON = (function() {
var replace = { var replace = {
'"': '\\"', '"': '\\"',
'\b': '\\b', '\b': '\\b',
@ -236,14 +242,14 @@ Ox.polyfill.JSON = (function() {
return ret; return ret;
} }
}; };
}()); }());
/*@ /*@
Ox.polyfill.keys <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys Ox.polyfill.keys <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
> Ox.polyfill.keys({a: 1, b: 2, c: 3}) > Ox.polyfill.keys({a: 1, b: 2, c: 3})
['a', 'b', 'c'] ['a', 'b', 'c']
@*/ @*/
Ox.polyfill.keys = function(object) { Ox.polyfill.keys = function(object) {
if (object !== Object(object)) { if (object !== Object(object)) {
throw new TypeError(); throw new TypeError();
} }
@ -252,16 +258,16 @@ Ox.polyfill.keys = function(object) {
Object.prototype.hasOwnProperty.call(object, key) && ret.push(key); Object.prototype.hasOwnProperty.call(object, key) && ret.push(key);
} }
return ret; return ret;
}; };
/*@ /*@
Ox.polyfill.lastIndexOf <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf Ox.polyfill.lastIndexOf <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
> Ox.polyfill.lastIndexOf.call([1, 2, 3, 2, 1], 2) > Ox.polyfill.lastIndexOf.call([1, 2, 3, 2, 1], 2)
3 3
> Ox.polyfill.lastIndexOf.call([1, 2, 3, 2, 1], 4) > Ox.polyfill.lastIndexOf.call([1, 2, 3, 2, 1], 4)
-1 -1
@*/ @*/
Ox.polyfill.lastIndexOf = function(value) { Ox.polyfill.lastIndexOf = function(value) {
if (this === void 0 || this === null) { if (this === void 0 || this === null) {
throw new TypeError(); throw new TypeError();
} }
@ -273,14 +279,14 @@ Ox.polyfill.lastIndexOf = function(value) {
} }
} }
return ret; return ret;
}; };
/*@ /*@
Ox.polyfill.map <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map Ox.polyfill.map <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
> Ox.polyfill.map.call([2, 1, 0], function(v, i) { return v == i; }) > Ox.polyfill.map.call([2, 1, 0], function(v, i) { return v == i; })
[false, true, false] [false, true, false]
@*/ @*/
Ox.polyfill.map = function(iterator, that) { Ox.polyfill.map = function(iterator, that) {
if (this === void 0 || this === null || typeof iterator !== 'function') { if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError(); throw new TypeError();
} }
@ -292,14 +298,14 @@ Ox.polyfill.map = function(iterator, that) {
} }
} }
return ret; return ret;
}; };
/*@ /*@
Ox.polyfill.reduce <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce Ox.polyfill.reduce <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
> Ox.polyfill.reduce.call([1, 2, 3], function(p, c, i) { return p + c + i; }, 1) > Ox.polyfill.reduce.call([1, 2, 3], function(p, c, i) { return p + c + i; }, 1)
10 10
@*/ @*/
Ox.polyfill.reduce = function(iterator, ret) { Ox.polyfill.reduce = function(iterator, ret) {
if (this === void 0 || this === null || typeof iterator !== 'function') { if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError(); throw new TypeError();
} }
@ -317,14 +323,14 @@ Ox.polyfill.reduce = function(iterator, ret) {
} }
} }
return ret; return ret;
}; };
/*@ /*@
Ox.polyfill.reduceRight <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduceRight Ox.polyfill.reduceRight <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduceRight
> Ox.polyfill.reduceRight.call([1, 2, 3], function(p, c, i) { return p + c + i; }, 1) > Ox.polyfill.reduceRight.call([1, 2, 3], function(p, c, i) { return p + c + i; }, 1)
10 10
@*/ @*/
Ox.polyfill.reduceRight = function(iterator, ret) { Ox.polyfill.reduceRight = function(iterator, ret) {
if (this === void 0 || this === null || typeof iterator !== 'function') { if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError(); throw new TypeError();
} }
@ -342,16 +348,16 @@ Ox.polyfill.reduceRight = function(iterator, ret) {
} }
} }
return ret; return ret;
}; };
/*@ /*@
Ox.polyfill.some <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some Ox.polyfill.some <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
> Ox.polyfill.some.call([2, 1, 0], function(v, i) { return v == i; }) > Ox.polyfill.some.call([2, 1, 0], function(v, i) { return v == i; })
true true
> Ox.polyfill.some.call([false, false, false], Ox.identity) > Ox.polyfill.some.call([false, false, false], Ox.identity)
false false
@*/ @*/
Ox.polyfill.some = function(iterator, that) { Ox.polyfill.some = function(iterator, that) {
if (this === void 0 || this === null || typeof iterator !== 'function') { if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError(); throw new TypeError();
} }
@ -363,33 +369,48 @@ Ox.polyfill.some = function(iterator, that) {
} }
} }
return ret; return ret;
}; };
/*@ /*@
Ox.polyfill.trim <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim Ox.polyfill.trim <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim
> Ox.polyfill.trim.call(' foo ') > Ox.polyfill.trim.call(' foo ')
'foo' 'foo'
@*/ @*/
Ox.polyfill.trim = function() { Ox.polyfill.trim = function() {
if (this === void 0 || this === null) { if (this === void 0 || this === null) {
throw new TypeError(); throw new TypeError();
} }
return this.replace(/^\s+|\s+$/g, ''); return this.replace(/^\s+|\s+$/g, '');
}; };
(function(window) { [
var key, log, object; [Array, ['isArray']],
for (key in Ox.polyfill) { [Array.prototype, [
object = key == 'bind' ? Function.prototype 'every', 'filter', 'forEach', 'indexOf', 'lastIndexOf',
: key == 'isArray' ? Array 'map', 'reduce', 'reduceRight', 'some']
: key == 'atob' || key == 'btoa' || key == 'JSON' ? window ],
: key == 'keys' ? Object [Function.prototype, ['bind']],
: key == 'trim' ? String.prototype [Object, ['keys']],
: Array.prototype; [String.prototype, ['trim']],
if (!object[key]) { [window, ['atob', 'btoa', 'JSON']]
].forEach(function(item) {
var object = item[0], keys = item[1];
keys.forEach(function(key) {
if (!key in object) {
if (canDefineProperty) {
Object.defineProperty(object, key, {
configurable: true,
enumerable: false,
writable: true,
value: Ox.polyfill[key]
});
} else {
object[key] = Ox.polyfill[key]; object[key] = Ox.polyfill[key];
} }
} }
});
});
// In IE8, window.console.log is an object, // In IE8, window.console.log is an object,
// in IE9, window.console.log.apply is undefined // in IE9, window.console.log.apply is undefined
// see http://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function // see http://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function
@ -405,4 +426,5 @@ Ox.polyfill.trim = function() {
); );
} }
} }
})(this); })(this);