Cleanup prototype references of built-ins and the _.isElement bizarro tests.

This commit is contained in:
John-David Dalton
2014-07-18 23:52:04 -07:00
parent 2f98cd9eb0
commit 60f57f9e4b
2 changed files with 67 additions and 48 deletions

View File

@@ -51,7 +51,10 @@
setProperty(Function.prototype, 'toString', (function() { setProperty(Function.prototype, 'toString', (function() {
function wrapper() { function wrapper() {
setProperty(Function.prototype, 'toString', fnToString); setProperty(Function.prototype, 'toString', fnToString);
var result = this === Set ? this.toString() : fnToString.call(this); var result = (this === window.ArrayBuffer || this === window.Set)
? this.toString()
: fnToString.call(this);
setProperty(Function.prototype, 'toString', wrapper); setProperty(Function.prototype, 'toString', wrapper);
return result; return result;
} }

View File

@@ -15,6 +15,13 @@
/** Used to store Lo-Dash to test for bad extensions/shims */ /** Used to store Lo-Dash to test for bad extensions/shims */
var lodashBizarro = root.lodashBizarro; var lodashBizarro = root.lodashBizarro;
/** Used for native method references */
var arrayProto = Array.prototype,
errorProto = Error.prototype,
funcProto = Function.prototype,
objectProto = Object.prototype,
stringProto = String.prototype;
/** Method and object shortcuts */ /** Method and object shortcuts */
var phantom = root.phantom, var phantom = root.phantom,
amd = root.define && define.amd, amd = root.define && define.amd,
@@ -27,10 +34,10 @@
JSON = root.JSON, JSON = root.JSON,
noop = function() {}, noop = function() {},
params = root.arguments, params = root.arguments,
push = Array.prototype.push, push = arrayProto.push,
slice = Array.prototype.slice, slice = arrayProto.slice,
system = root.system, system = root.system,
toString = Object.prototype.toString; toString = objectProto.toString;
/** The file path of the Lo-Dash file to test */ /** The file path of the Lo-Dash file to test */
var filePath = (function() { var filePath = (function() {
@@ -331,16 +338,19 @@
_._baseEach = baseEach.baseEach || baseEach['default'] || baseEach; _._baseEach = baseEach.baseEach || baseEach['default'] || baseEach;
} }
// allow bypassing native checks // allow bypassing native checks
var _fnToString = Function.prototype.toString; var _fnToString = funcProto.toString;
setProperty(Function.prototype, 'toString', function wrapper() { setProperty(funcProto, 'toString', function wrapper() {
setProperty(Function.prototype, 'toString', _fnToString); setProperty(funcProto, 'toString', _fnToString);
var result = this === Set ? this.toString() : _fnToString.call(this); var result = (this === root.ArrayBuffer || this === root.Set)
setProperty(Function.prototype, 'toString', wrapper); ? this.toString()
: _fnToString.call(this);
setProperty(funcProto, 'toString', wrapper);
return result; return result;
}); });
// add extensions // add extensions
Function.prototype._method = _.noop; funcProto._method = _.noop;
// set bad shims // set bad shims
var _isArray = Array.isArray; var _isArray = Array.isArray;
@@ -361,8 +371,8 @@
var _keys = Object.keys; var _keys = Object.keys;
setProperty(Object, 'keys', _.noop); setProperty(Object, 'keys', _.noop);
var _hasOwnProperty = Object.prototype.hasOwnProperty; var _hasOwnProperty = objectProto.hasOwnProperty;
setProperty(Object.prototype, 'hasOwnProperty', function(key) { setProperty(objectProto, 'hasOwnProperty', function(key) {
if (key == '1' && _.isArguments(this) && _.isEqual(_.values(this), [0, 0])) { if (key == '1' && _.isArguments(this) && _.isEqual(_.values(this), [0, 0])) {
throw new Error; throw new Error;
} }
@@ -372,12 +382,12 @@
var _isFinite = Number.isFinite; var _isFinite = Number.isFinite;
setProperty(Number, 'isFinite', _.noop); setProperty(Number, 'isFinite', _.noop);
var _contains = String.prototype.contains; var _contains = stringProto.contains;
setProperty(String.prototype, 'contains', _contains ? _.noop : Boolean); setProperty(stringProto, 'contains', _contains ? _.noop : Boolean);
var _ArrayBuffer = root.ArrayBuffer; var _ArrayBuffer = ArrayBuffer;
if (root.Uint8Array && _ArrayBuffer && !new _ArrayBuffer(0).slice) { if (Uint8Array && new ArrayBuffer(0).slice) {
setProperty(window, 'ArrayBuffer', function(byteLength) { setProperty(root, 'ArrayBuffer', function(byteLength) {
var buffer = new _ArrayBuffer(byteLength); var buffer = new _ArrayBuffer(byteLength);
buffer.slice = !byteLength ? slice : function() { buffer.slice = !byteLength ? slice : function() {
var newBuffer = new _ArrayBuffer(byteLength), var newBuffer = new _ArrayBuffer(byteLength),
@@ -388,6 +398,8 @@
}; };
return buffer; return buffer;
}); });
setPropertu(ArrayBuffer, 'toString', _.constant(String(toString).replace(/toString/g, 'ArrayBuffer')));
} }
var _Float64Array = root.Float64Array; var _Float64Array = root.Float64Array;
setProperty(root, 'Float64Array', _Float64Array ? _.noop : root.Uint8Array); setProperty(root, 'Float64Array', _Float64Array ? _.noop : root.Uint8Array);
@@ -416,8 +428,8 @@
setProperty(Object, 'getPrototypeOf', _getPrototypeOf); setProperty(Object, 'getPrototypeOf', _getPrototypeOf);
setProperty(Object, 'keys', _keys); setProperty(Object, 'keys', _keys);
setProperty(Object.prototype, 'hasOwnProperty', _hasOwnProperty); setProperty(objectProto, 'hasOwnProperty', _hasOwnProperty);
setProperty(Function.prototype, 'toString', _fnToString); setProperty(funcProto, 'toString', _fnToString);
if (_isFinite) { if (_isFinite) {
setProperty(Number, 'isFinite', _isFinite); setProperty(Number, 'isFinite', _isFinite);
@@ -425,9 +437,9 @@
delete Number.isFinite; delete Number.isFinite;
} }
if (_contains) { if (_contains) {
setProperty(String.prototype, 'contains', _contains); setProperty(stringProto, 'contains', _contains);
} else { } else {
delete String.prototype.contains; delete stringProto.contains;
} }
if (_ArrayBuffer) { if (_ArrayBuffer) {
setProperty(root, 'ArrayBuffer', _ArrayBuffer); setProperty(root, 'ArrayBuffer', _ArrayBuffer);
@@ -439,7 +451,7 @@
} }
delete root.window; delete root.window;
delete root.WinRTError; delete root.WinRTError;
delete Function.prototype._method; delete funcProto._method;
}()); }());
// add values from an iframe // add values from an iframe
@@ -1141,7 +1153,7 @@
test('should work with an array `object` argument', 1, function() { test('should work with an array `object` argument', 1, function() {
var array = ['push', 'pop']; var array = ['push', 'pop'];
_.bindAll(array); _.bindAll(array);
strictEqual(array.pop, Array.prototype.pop); strictEqual(array.pop, arrayProto.pop);
}); });
test('should work with `arguments` objects as secondary arguments', 1, function() { test('should work with `arguments` objects as secondary arguments', 1, function() {
@@ -2097,7 +2109,7 @@
test('should support binding built-in methods', 2, function() { test('should support binding built-in methods', 2, function() {
var object = { 'a': 1 }, var object = { 'a': 1 },
callback = _.callback(Object.prototype.hasOwnProperty, object); callback = _.callback(objectProto.hasOwnProperty, object);
strictEqual(callback('a'), true); strictEqual(callback('a'), true);
@@ -4057,16 +4069,16 @@
test('`_.' + methodName + '` does not iterate over non-enumerable properties (test in IE < 9)', 10, function() { test('`_.' + methodName + '` does not iterate over non-enumerable properties (test in IE < 9)', 10, function() {
_.forOwn({ _.forOwn({
'Array': Array.prototype, 'Array': arrayProto,
'Boolean': Boolean.prototype, 'Boolean': Boolean.prototype,
'Date': Date.prototype, 'Date': Date.prototype,
'Error': Error.prototype, 'Error': errorProto,
'Function': Function.prototype, 'Function': funcProto,
'Object': Object.prototype, 'Object': objectProto,
'Number': Number.prototype, 'Number': Number.prototype,
'TypeError': TypeError.prototype, 'TypeError': TypeError.prototype,
'RegExp': RegExp.prototype, 'RegExp': RegExp.prototype,
'String': String.prototype 'String': stringProto
}, },
function(proto, key) { function(proto, key) {
var message = 'non-enumerable properties on ' + key + '.prototype', var message = 'non-enumerable properties on ' + key + '.prototype',
@@ -4993,11 +5005,15 @@
}); });
test('should use a stronger check in browsers', 2, function() { test('should use a stronger check in browsers', 2, function() {
var expected = !body; var support = _.support,
expected = !(support.dom && support.nodeClass);
strictEqual(_.isElement(new Element), expected); strictEqual(_.isElement(new Element), expected);
if (lodashBizarro && document) { if (lodashBizarro) {
strictEqual(lodashBizarro.isElement(new Element), !expected); support = lodashBizarro.support;
expected = !(support.dom && support.nodeClass);
strictEqual(lodashBizarro.isElement(new Element), expected);
} }
else { else {
skipTest(); skipTest();
@@ -5071,7 +5087,7 @@
test('should work with jQuery/MooTools DOM query collections', 1, function() { test('should work with jQuery/MooTools DOM query collections', 1, function() {
function Foo(elements) { push.apply(this, elements); } function Foo(elements) { push.apply(this, elements); }
Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; Foo.prototype = { 'length': 0, 'splice': arrayProto.splice };
strictEqual(_.isEmpty(new Foo([])), true); strictEqual(_.isEmpty(new Foo([])), true);
}); });
@@ -6372,11 +6388,11 @@
}); });
test('`_.' + methodName + '` should return an empty array for `null` or `undefined` values', 2, function() { test('`_.' + methodName + '` should return an empty array for `null` or `undefined` values', 2, function() {
Object.prototype.a = 1; objectProto.a = 1;
_.each([null, undefined], function(value) { _.each([null, undefined], function(value) {
deepEqual(func(value), []); deepEqual(func(value), []);
}); });
delete Object.prototype.a; delete objectProto.a;
}); });
test('`_.' + methodName + '` should return keys for custom properties on arrays', 1, function() { test('`_.' + methodName + '` should return keys for custom properties on arrays', 1, function() {
@@ -6389,9 +6405,9 @@
test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of arrays', 1, function() { test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of arrays', 1, function() {
var expected = isKeys ? ['0'] : ['0', 'a']; var expected = isKeys ? ['0'] : ['0', 'a'];
Array.prototype.a = 1; arrayProto.a = 1;
deepEqual(func([1]).sort(), expected); deepEqual(func([1]).sort(), expected);
delete Array.prototype.a; delete arrayProto.a;
}); });
test('`_.' + methodName + '` should work with `arguments` objects (test in IE < 9)', 1, function() { test('`_.' + methodName + '` should work with `arguments` objects (test in IE < 9)', 1, function() {
@@ -6418,9 +6434,9 @@
if (!(isPhantom || isStrict)) { if (!(isPhantom || isStrict)) {
var expected = isKeys ? ['0', '1', '2'] : ['0', '1', '2', 'a']; var expected = isKeys ? ['0', '1', '2'] : ['0', '1', '2', 'a'];
Object.prototype.a = 1; objectProto.a = 1;
deepEqual(func(args).sort(), expected); deepEqual(func(args).sort(), expected);
delete Object.prototype.a; delete objectProto.a;
} }
else { else {
skipTest(); skipTest();
@@ -6441,9 +6457,9 @@
test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of string objects', 1, function() { test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of string objects', 1, function() {
var expected = isKeys ? ['0'] : ['0', 'a']; var expected = isKeys ? ['0'] : ['0', 'a'];
String.prototype.a = 1; stringProto.a = 1;
deepEqual(func(Object('a')).sort(), expected); deepEqual(func(Object('a')).sort(), expected);
delete String.prototype.a; delete stringProto.a;
}); });
test('`_.' + methodName + '` fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { test('`_.' + methodName + '` fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() {
@@ -7587,11 +7603,11 @@
}); });
test('should return an empty object when `object` is `null` or `undefined`', 2, function() { test('should return an empty object when `object` is `null` or `undefined`', 2, function() {
Object.prototype.a = 1; objectProto.a = 1;
_.each([null, undefined], function(value) { _.each([null, undefined], function(value) {
deepEqual(_.omit(value, 'valueOf'), {}); deepEqual(_.omit(value, 'valueOf'), {});
}); });
delete Object.prototype.a; delete objectProto.a;
}); });
test('should work with `arguments` objects as secondary arguments', 1, function() { test('should work with `arguments` objects as secondary arguments', 1, function() {
@@ -7603,13 +7619,13 @@
}); });
test('should work with a primitive `object` argument', 1, function() { test('should work with a primitive `object` argument', 1, function() {
String.prototype.a = 1; stringProto.a = 1;
String.prototype.b = 2; stringProto.b = 2;
deepEqual(_.omit('', 'b'), { 'a': 1 }); deepEqual(_.omit('', 'b'), { 'a': 1 });
delete String.prototype.a; delete stringProto.a;
delete String.prototype.b; delete stringProto.b;
}); });
test('should work with a predicate argument', 1, function() { test('should work with a predicate argument', 1, function() {
@@ -9136,7 +9152,7 @@
test('should work with jQuery/MooTools DOM query collections', 1, function() { test('should work with jQuery/MooTools DOM query collections', 1, function() {
function Foo(elements) { push.apply(this, elements); } function Foo(elements) { push.apply(this, elements); }
Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; Foo.prototype = { 'length': 0, 'splice': arrayProto.splice };
strictEqual(_.size(new Foo(array)), 3); strictEqual(_.size(new Foo(array)), 3);
}); });